From 180c18f6bf63e8ea54c0ca762ac62224a6d9facf Mon Sep 17 00:00:00 2001 From: Alinson Xavier Date: Fri, 21 Jul 2017 18:12:45 -0400 Subject: [PATCH] Merge branch 'feature/kotlin' into dev --- .gitignore | 1 + accept_images.sh | 3 - .../activities/ActivityContextModule.java | 19 +- ...ityModule.java => BaseActivityModule.java} | 15 +- .../androidbase/utils/StyledResources.java | 13 +- build.gradle | 2 + build.sh | 22 + gradle.properties | 4 +- uhabits-android/build.gradle | 29 +- .../render_different_color.png | Bin 0 -> 1460 bytes .../list/CheckmarkPanelView/render_offset.png | Bin 0 -> 1216 bytes .../CheckmarkPanelView/render_reversed.png | Bin 0 -> 1490 bytes .../habits/list/NumberPanelView/render.png | Bin 0 -> 7386 bytes .../render_different_color.png | Bin 0 -> 7389 bytes .../list/NumberPanelView/render_offset.png | Bin 0 -> 7832 bytes .../list/NumberPanelView/render_reversed.png | Bin 0 -> 7380 bytes .../widgets/HistoryWidget/render.png | Bin 35673 -> 36111 bytes .../views-v19/widgets/ScoreWidget/render.png | Bin 18921 -> 18545 bytes .../common/RingView/renderDifferentParams.png | Bin 15050 -> 14764 bytes .../common/ScoreChart/renderYearly.png | Bin 10529 -> 10630 bytes .../render_explicit_check.png | Bin 577 -> 585 bytes .../habits/list/CheckmarkPanelView/render.png | Bin 1452 -> 1470 bytes .../render_different_color.png | Bin 0 -> 1441 bytes .../list/CheckmarkPanelView/render_offset.png | Bin 0 -> 1265 bytes .../CheckmarkPanelView/render_reversed.png | Bin 0 -> 1480 bytes .../habits/list/HabitCardView/render.png | Bin 5118 -> 5137 bytes .../list/HabitCardView/render_changed.png | Bin 5118 -> 5137 bytes .../list/HabitCardView/render_numerical.png | Bin 0 -> 10845 bytes .../list/HabitCardView/render_selected.png | Bin 5174 -> 5209 bytes .../habits/list/HeaderView/render.png | Bin 5579 -> 5290 bytes .../habits/list/HeaderView/render_reverse.png | Bin 5560 -> 5287 bytes .../habits/list/NumberPanelView/render.png | Bin 0 -> 7590 bytes .../render_different_color.png | Bin 0 -> 7524 bytes .../list/NumberPanelView/render_offset.png | Bin 0 -> 8057 bytes .../list/NumberPanelView/render_reversed.png | Bin 0 -> 7588 bytes .../habits/show/FrequencyCard/render.png | Bin 19291 -> 24936 bytes .../habits/show/SubtitleCard/render.png | Bin 10308 -> 15716 bytes .../widgets/HistoryWidget/render.png | Bin 36577 -> 37035 bytes .../views-v21/widgets/ScoreWidget/render.png | Bin 21039 -> 21307 bytes .../org/isoron/uhabits/BaseAndroidTest.java | 40 +- .../java/org/isoron/uhabits/BaseViewTest.java | 9 +- .../org/isoron/uhabits/HabitFixtures.java | 3 + .../uhabits/HabitsActivityTestComponent.kt | 53 +++ ...va => HabitsApplicationTestComponent.java} | 6 +- .../uhabits/acceptance/steps/CommonSteps.java | 3 +- .../acceptance/steps/ListHabitsSteps.java | 29 +- .../list/views/CheckmarkButtonViewTest.java | 87 ---- .../list/views/CheckmarkButtonViewTest.kt | 99 ++++ .../list/views/CheckmarkPanelViewTest.java | 96 ---- .../list/views/CheckmarkPanelViewTest.kt | 110 +++++ .../habits/list/views/HabitCardViewTest.java | 86 ---- .../habits/list/views/HabitCardViewTest.kt | 86 ++++ .../habits/list/views/HeaderViewTest.java | 8 +- .../habits/list/views/HintViewTest.java | 3 +- .../list/views/NumberButtonViewTest.java | 95 ---- .../habits/list/views/NumberButtonViewTest.kt | 106 +++++ .../habits/list/views/NumberPanelViewTest.kt | 105 +++++ .../activities/AndroidThemeSwitcher.java | 63 --- ...kage-info.java => AndroidThemeSwitcher.kt} | 32 +- .../isoron/uhabits/activities/HabitModule.kt | 13 +- .../uhabits/activities/HabitsActivity.java | 78 ---- .../uhabits/activities/HabitsActivity.kt | 57 +++ .../activities/HabitsActivityComponent.java | 68 --- .../activities/HabitsActivityComponent.kt | 55 +++ ...ityModule.java => HabitsActivityModule.kt} | 17 +- .../uhabits/activities/HabitsDirFinder.java | 47 -- ...CardViewHolder.java => HabitsDirFinder.kt} | 20 +- .../activities/about/AboutActivity.java | 4 +- .../activities/about/package-info.java | 23 - .../common/dialogs/NumberPickerFactory.kt | 91 ++++ .../activities/common/views/BarChart.java | 2 +- .../activities/common/views/RingView.java | 27 +- .../common/views/ScrollableChart.java | 2 +- .../common/views/TaskProgressBar.kt | 66 +++ .../activities/common/views/package-info.java | 23 - .../habits/edit/EditHabitDialog.java | 2 +- .../activities/habits/edit/package-info.java | 23 - .../habits/list/ListHabitsActivity.java | 102 ---- .../habits/list/ListHabitsActivity.kt | 70 +++ .../habits/list/ListHabitsController.java | 164 ------- .../habits/list/ListHabitsMenu.java | 129 ----- .../activities/habits/list/ListHabitsMenu.kt | 111 +++++ .../habits/list/ListHabitsModule.java | 69 --- .../habits/list/ListHabitsModule.kt | 58 +++ .../habits/list/ListHabitsRootView.java | 198 -------- .../habits/list/ListHabitsRootView.kt | 135 ++++++ .../habits/list/ListHabitsScreen.java | 441 ------------------ .../habits/list/ListHabitsScreen.kt | 264 +++++++++++ .../habits/list/ListHabitsSelectionMenu.java | 145 ------ .../habits/list/ListHabitsSelectionMenu.kt | 95 ++++ .../activities/habits/list/package-info.java | 23 - .../habits/list/views/ButtonPanelView.kt | 88 ++++ .../list/views/CheckmarkButtonView.java | 194 -------- .../habits/list/views/CheckmarkButtonView.kt | 123 +++++ .../habits/list/views/CheckmarkPanelView.java | 243 ---------- .../habits/list/views/CheckmarkPanelView.kt | 71 +++ .../habits/list/views/EmptyListView.kt | 52 +++ .../list/views/HabitCardListAdapter.java | 5 +- .../list/views/HabitCardListController.java | 334 ------------- .../list/views/HabitCardListController.kt | 167 +++++++ .../habits/list/views/HabitCardListView.java | 282 ----------- .../habits/list/views/HabitCardListView.kt | 171 +++++++ .../habits/list/views/HabitCardView.java | 406 ---------------- .../habits/list/views/HabitCardView.kt | 253 ++++++++++ .../habits/list/views/HabitCardViewHolder.kt} | 11 +- .../habits/list/views/HeaderView.java | 192 -------- .../habits/list/views/HeaderView.kt | 136 ++++++ .../habits/list/views/HintView.java | 134 ------ .../activities/habits/list/views/HintView.kt | 91 ++++ .../habits/list/views/NumberButtonView.java | 239 ---------- .../habits/list/views/NumberButtonView.kt | 160 +++++++ .../habits/list/views/NumberPanelView.java | 259 ---------- .../habits/list/views/NumberPanelView.kt | 84 ++++ .../habits/list/views/ShadowView.kt | 39 ++ .../habits/show/ShowHabitActivity.java | 2 +- .../activities/habits/show/package-info.java | 24 - .../activities/intro/package-info.java | 23 - .../uhabits/activities/package-info.java | 23 - .../activities/settings/SettingsFragment.java | 10 +- .../activities/settings/package-info.java | 23 - .../java/org/isoron/uhabits/package-info.java | 23 - .../preferences/SharedPreferencesStorage.java | 2 +- .../isoron/uhabits/utils/ViewExtensions.kt | 99 ++++ .../isoron/uhabits/utils/package-info.java | 23 - .../isoron/uhabits/widgets/package-info.java | 23 - .../uhabits/widgets/views/package-info.java | 23 - .../{toolbar_shadow.xml => shadow.xml} | 0 .../src/main/res/layout/list_habits.xml | 96 ---- .../res/layout/list_habits_button_preview.xml | 67 --- .../res/layout/list_habits_panel_preview.xml | 107 ----- .../main/res/layout/list_habits_preview.xml | 123 ----- .../src/main/res/layout/toolbar.xml | 28 ++ .../src/main/res/values/styles.xml | 2 +- ...dUnitTest.java => BaseAndroidJVMTest.java} | 6 +- .../habits/list/ListHabitsMenuTest.java | 150 ------ .../habits/list/ListHabitsMenuTest.kt | 128 +++++ .../habits/list/ListHabitsScreenTest.java | 255 ---------- .../habits/list/ListHabitsScreenTest.kt | 213 +++++++++ .../HabitCardListControllerTest.java | 174 ------- .../HabitCardListControllerTest.kt | 122 +++++ .../habits/list/controllers/package-info.java | 23 - .../receivers/ReminderControllerTest.java | 2 +- .../receivers/WidgetControllerTest.java | 2 +- .../models/sqlite/records/package-info.java | 25 - .../uhabits/core/preferences/Preferences.java | 13 +- .../core/tasks/SingleThreadTaskRunner.java | 10 +- .../models/sqlite/SQLiteHabitListTest.java | 2 - 147 files changed, 3835 insertions(+), 5594 deletions(-) delete mode 100755 accept_images.sh rename uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitModule.java => android-base/src/main/java/org/isoron/androidbase/activities/ActivityContextModule.java (68%) rename android-base/src/main/java/org/isoron/androidbase/activities/{ActivityModule.java => BaseActivityModule.java} (79%) create mode 100644 uhabits-android/src/androidTest/assets/views-v19/habits/list/CheckmarkPanelView/render_different_color.png create mode 100644 uhabits-android/src/androidTest/assets/views-v19/habits/list/CheckmarkPanelView/render_offset.png create mode 100644 uhabits-android/src/androidTest/assets/views-v19/habits/list/CheckmarkPanelView/render_reversed.png create mode 100644 uhabits-android/src/androidTest/assets/views-v19/habits/list/NumberPanelView/render.png create mode 100644 uhabits-android/src/androidTest/assets/views-v19/habits/list/NumberPanelView/render_different_color.png create mode 100644 uhabits-android/src/androidTest/assets/views-v19/habits/list/NumberPanelView/render_offset.png create mode 100644 uhabits-android/src/androidTest/assets/views-v19/habits/list/NumberPanelView/render_reversed.png create mode 100644 uhabits-android/src/androidTest/assets/views-v21/habits/list/CheckmarkPanelView/render_different_color.png create mode 100644 uhabits-android/src/androidTest/assets/views-v21/habits/list/CheckmarkPanelView/render_offset.png create mode 100644 uhabits-android/src/androidTest/assets/views-v21/habits/list/CheckmarkPanelView/render_reversed.png create mode 100644 uhabits-android/src/androidTest/assets/views-v21/habits/list/HabitCardView/render_numerical.png create mode 100644 uhabits-android/src/androidTest/assets/views-v21/habits/list/NumberPanelView/render.png create mode 100644 uhabits-android/src/androidTest/assets/views-v21/habits/list/NumberPanelView/render_different_color.png create mode 100644 uhabits-android/src/androidTest/assets/views-v21/habits/list/NumberPanelView/render_offset.png create mode 100644 uhabits-android/src/androidTest/assets/views-v21/habits/list/NumberPanelView/render_reversed.png create mode 100644 uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitsActivityTestComponent.kt rename uhabits-android/src/androidTest/java/org/isoron/uhabits/{AndroidTestComponent.java => HabitsApplicationTestComponent.java} (90%) delete mode 100644 uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonViewTest.java create mode 100644 uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonViewTest.kt delete mode 100644 uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelViewTest.java create mode 100644 uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelViewTest.kt delete mode 100644 uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/HabitCardViewTest.java create mode 100644 uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/HabitCardViewTest.kt delete mode 100644 uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.java create mode 100644 uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt create mode 100644 uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelViewTest.kt delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/AndroidThemeSwitcher.java rename uhabits-android/src/main/java/org/isoron/uhabits/activities/{habits/show/views/package-info.java => AndroidThemeSwitcher.kt} (53%) rename uhabits-core/src/main/java/org/isoron/uhabits/core/io/package-info.java => uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitModule.kt (80%) delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsActivity.java create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsActivity.kt delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsActivityComponent.java create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsActivityComponent.kt rename uhabits-android/src/main/java/org/isoron/uhabits/activities/{HabitsActivityModule.java => HabitsActivityModule.kt} (73%) delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsDirFinder.java rename uhabits-android/src/main/java/org/isoron/uhabits/activities/{habits/list/views/HabitCardViewHolder.java => HabitsDirFinder.kt} (62%) delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/about/package-info.java create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/TaskProgressBar.kt delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/package-info.java delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/package-info.java delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsActivity.java create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsActivity.kt delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsController.java delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenu.java create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenu.kt delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsModule.java create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsModule.kt delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsRootView.java create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsRootView.kt delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.java create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsSelectionMenu.java create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsSelectionMenu.kt delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/package-info.java create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/ButtonPanelView.kt delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.java create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.java create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/EmptyListView.kt delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListController.java create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListController.kt delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.java create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.kt delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.java create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt rename uhabits-android/src/main/java/org/isoron/uhabits/{tasks/package-info.java => activities/habits/list/views/HabitCardViewHolder.kt} (80%) delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HeaderView.java create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HeaderView.kt delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HintView.java create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HintView.kt delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.java create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.java create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.kt create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/ShadowView.kt delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/package-info.java delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/intro/package-info.java delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/package-info.java delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/package-info.java delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/package-info.java create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/utils/ViewExtensions.kt delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/utils/package-info.java delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/widgets/package-info.java delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/package-info.java rename uhabits-android/src/main/res/drawable/{toolbar_shadow.xml => shadow.xml} (100%) delete mode 100644 uhabits-android/src/main/res/layout/list_habits.xml delete mode 100644 uhabits-android/src/main/res/layout/list_habits_button_preview.xml delete mode 100644 uhabits-android/src/main/res/layout/list_habits_panel_preview.xml delete mode 100644 uhabits-android/src/main/res/layout/list_habits_preview.xml create mode 100644 uhabits-android/src/main/res/layout/toolbar.xml rename uhabits-android/src/test/java/org/isoron/uhabits/{BaseAndroidUnitTest.java => BaseAndroidJVMTest.java} (98%) delete mode 100644 uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenuTest.java create mode 100644 uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenuTest.kt delete mode 100644 uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreenTest.java create mode 100644 uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreenTest.kt delete mode 100644 uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/controllers/HabitCardListControllerTest.java create mode 100644 uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/controllers/HabitCardListControllerTest.kt delete mode 100644 uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/controllers/package-info.java delete mode 100644 uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/records/package-info.java diff --git a/.gitignore b/.gitignore index cce506928..0b81ffa3c 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ gen/ local.properties crowdin.yaml local +tmp/ diff --git a/accept_images.sh b/accept_images.sh deleted file mode 100755 index e8e14d51c..000000000 --- a/accept_images.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -find uhabits-android/build/outputs/failed/test-screenshots -name '*.expected*' -delete -rsync -av uhabits-android/build/outputs/failed/test-screenshots/ uhabits-android/src/androidTest/assets/ diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitModule.java b/android-base/src/main/java/org/isoron/androidbase/activities/ActivityContextModule.java similarity index 68% rename from uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitModule.java rename to android-base/src/main/java/org/isoron/androidbase/activities/ActivityContextModule.java index 105b9a6b5..af7e26442 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitModule.java +++ b/android-base/src/main/java/org/isoron/androidbase/activities/ActivityContextModule.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Álinson Santos Xavier + * Copyright (C) 2016 Álinson Santos Xavier * * This file is part of Loop Habit Tracker. * @@ -17,25 +17,26 @@ * with this program. If not, see . */ -package org.isoron.uhabits.activities; +package org.isoron.androidbase.activities; -import org.isoron.uhabits.core.models.*; +import android.content.*; import dagger.*; @Module -public class HabitModule +public class ActivityContextModule { - private final Habit habit; + private Context context; - public HabitModule(Habit habit) + public ActivityContextModule(Context context) { - this.habit = habit; + this.context = context; } @Provides - public Habit getHabit() + @ActivityContext + public Context getContext() { - return habit; + return context; } } diff --git a/android-base/src/main/java/org/isoron/androidbase/activities/ActivityModule.java b/android-base/src/main/java/org/isoron/androidbase/activities/BaseActivityModule.java similarity index 79% rename from android-base/src/main/java/org/isoron/androidbase/activities/ActivityModule.java rename to android-base/src/main/java/org/isoron/androidbase/activities/BaseActivityModule.java index f3910c989..96e5ec476 100644 --- a/android-base/src/main/java/org/isoron/androidbase/activities/ActivityModule.java +++ b/android-base/src/main/java/org/isoron/androidbase/activities/BaseActivityModule.java @@ -19,29 +19,20 @@ package org.isoron.androidbase.activities; -import android.content.*; - import dagger.*; @Module -public class ActivityModule +public class BaseActivityModule { private BaseActivity activity; - public ActivityModule(BaseActivity activity) + public BaseActivityModule(BaseActivity activity) { this.activity = activity; } @Provides - public BaseActivity getActivity() - { - return activity; - } - - @Provides - @ActivityContext - public Context getContext() + public BaseActivity getBaseActivity() { return activity; } diff --git a/android-base/src/main/java/org/isoron/androidbase/utils/StyledResources.java b/android-base/src/main/java/org/isoron/androidbase/utils/StyledResources.java index c72686936..d15766f95 100644 --- a/android-base/src/main/java/org/isoron/androidbase/utils/StyledResources.java +++ b/android-base/src/main/java/org/isoron/androidbase/utils/StyledResources.java @@ -51,6 +51,15 @@ public boolean getBoolean(@AttrRes int attrId) return bool; } + public int getDimension(@AttrRes int attrId) + { + TypedArray ta = getTypedArray(attrId); + int dim = ta.getDimensionPixelSize(0, 0); + ta.recycle(); + + return dim; + } + public int getColor(@AttrRes int attrId) { TypedArray ta = getTypedArray(attrId); @@ -80,13 +89,13 @@ public float getFloat(@AttrRes int attrId) public int[] getPalette() { - int resourceId = getStyleResource(R.attr.palette); + int resourceId = getResource(R.attr.palette); if (resourceId < 0) throw new RuntimeException("resource not found"); return context.getResources().getIntArray(resourceId); } - int getStyleResource(@AttrRes int attrId) + public int getResource(@AttrRes int attrId) { TypedArray ta = getTypedArray(attrId); int resourceId = ta.getResourceId(0, -1); diff --git a/build.gradle b/build.gradle index dae129a17..7d8de18e5 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,5 @@ buildscript { + ext.kotlin_version = '1.1.2-4' repositories { jcenter() maven { url 'https://maven.google.com' } @@ -10,6 +11,7 @@ buildscript { classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.6.4' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' classpath 'org.jacoco:org.jacoco.core:+' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/build.sh b/build.sh index 74d4fc268..471172bb9 100755 --- a/build.sh +++ b/build.sh @@ -198,6 +198,18 @@ uninstall_test_apk() { $ADB uninstall ${PACKAGE_NAME}.test || fail } +fetch_images() { + rm -rf tmp/test-screenshots > /dev/null + mkdir -p tmp/ + adb pull /sdcard/Android/data/org.isoron.uhabits/files/test-screenshots tmp/ + adb shell rm -rf /sdcard/Android/data/org.isoron.uhabits/files/test-screenshots +} + +accept_images() { + find tmp/test-screenshots -name '*.expected*' -delete + rsync -av tmp/test-screenshots/ uhabits-android/src/androidTest/assets/ +} + run_local_tests() { clean_output_dir run_adb_as_root @@ -263,6 +275,14 @@ case "$1" in run_local_tests ;; + fetch-images) + fetch_images + ;; + + accept-images) + accept_images + ;; + install) shift; parse_opts $* build_apk @@ -278,6 +298,8 @@ case "$1" in ci-tests Start emulator silently, run tests then kill emulator local-tests Run all tests on connected device install Install app on connected device + fetch-images Fetches failed view test images from device + accept-images Copies fetched images to corresponding assets folder Options: -u --uninstall-first Uninstall existing APK first diff --git a/gradle.properties b/gradle.properties index 57a1784b0..2c6d0198f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ -org.gradle.parallel=true +org.gradle.parallel=false org.gradle.daemon=true -org.gradle.jvmargs=-Xms1024m -Xmx4096m -XX:MaxPermSize=2048m +org.gradle.jvmargs=-Xms2048m -Xmx2048m -XX:MaxPermSize=2048m diff --git a/uhabits-android/build.gradle b/uhabits-android/build.gradle index deb171daa..9f67c7c0a 100644 --- a/uhabits-android/build.gradle +++ b/uhabits-android/build.gradle @@ -1,5 +1,7 @@ apply plugin: 'idea' apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-kapt' apply plugin: 'jacoco' android { @@ -11,6 +13,13 @@ android { minSdkVersion 19 targetSdkVersion 25 testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + testInstrumentationRunnerArgument "size", "medium" + + javaCompileOptions { + annotationProcessorOptions { + includeCompileClasspath false + } + } } buildTypes { @@ -64,18 +73,16 @@ dependencies { implementation 'com.google.dagger:dagger:2.9' implementation 'com.jakewharton:butterknife:8.6.1-SNAPSHOT' implementation 'org.apmem.tools:layouts:1.10' - implementation 'org.jetbrains:annotations-java5:15.0' implementation 'com.google.code.gson:gson:2.7' implementation 'com.google.code.findbugs:jsr305:3.0.2' + implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" + compileOnly 'javax.annotation:jsr250-api:1.0' compileOnly 'com.google.auto.factory:auto-factory:1.0-beta3' - annotationProcessor 'com.google.dagger:dagger-compiler:2.9' - annotationProcessor 'com.jakewharton:butterknife-compiler:8.6.1-SNAPSHOT' - annotationProcessor 'com.google.auto.factory:auto-factory:1.0-beta3' + kapt 'com.google.dagger:dagger-compiler:2.9' + kapt 'com.jakewharton:butterknife-compiler:8.6.1-SNAPSHOT' + kapt 'com.google.auto.factory:auto-factory:1.0-beta3' - androidTestAnnotationProcessor 'com.google.auto.factory:auto-factory:1.0-beta3' - androidTestAnnotationProcessor 'com.google.dagger:dagger-compiler:2.9' - androidTestAnnotationProcessor 'com.jakewharton:butterknife-compiler:8.6.1-SNAPSHOT' androidTestImplementation 'com.android.support.test.espresso:espresso-contrib:2.2.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:2.2.2' androidTestImplementation 'com.android.support.test.uiautomator:uiautomator-v18:2.1.1' @@ -87,6 +94,7 @@ dependencies { androidTestImplementation 'com.android.support.test:runner:0.5' androidTestImplementation 'com.google.guava:guava:20.0' androidTestImplementation project(":uhabits-core") + kaptAndroidTest 'com.google.dagger:dagger-compiler:2.9' // mockito-android 2+ includes net.bytebuddy, which causes tests to fail. // Excluding the package net.bytebuddy on AndroidManifest.xml breaks some @@ -94,9 +102,6 @@ dependencies { androidTestImplementation "org.mockito:mockito-core:1+" androidTestImplementation "com.google.dexmaker:dexmaker-mockito:+" - testAnnotationProcessor 'com.google.auto.factory:auto-factory:1.0-beta3' - testAnnotationProcessor 'com.google.dagger:dagger-compiler:2.9' - testAnnotationProcessor 'com.jakewharton:butterknife-compiler:8.6.1-SNAPSHOT' testImplementation 'com.google.dagger:dagger:2.9' testImplementation "org.mockito:mockito-core:2.8.9" testImplementation "org.mockito:mockito-inline:2.8.9" @@ -114,6 +119,10 @@ repositories { mavenCentral() } +kapt { + correctErrorTypes = true +} + task coverageReport(type: JacocoReport) { jacocoClasspath = configurations['androidJacocoAnt'] diff --git a/uhabits-android/src/androidTest/assets/views-v19/habits/list/CheckmarkPanelView/render_different_color.png b/uhabits-android/src/androidTest/assets/views-v19/habits/list/CheckmarkPanelView/render_different_color.png new file mode 100644 index 0000000000000000000000000000000000000000..84302fe2214a5ca75d77897695de06017dee9fa5 GIT binary patch literal 1460 zcmcJP`#;lr9LK*quBStsh$W=rK`OU0w;8RujFZdU&Q{Xxpq7=EOInn-~B^KcB1sKQGNK23r6C z&_sKqFaQ9#3D&37Rl%&gM9%^bWg-$CtPTcA{oHK;P{E^7M}iYeW`_89!#@n)%=7Dl z$W#;xM;Yq7>X35l9XT_gH8`4bKQ+@kBtR=^VXSjcD8qc-%GmNYhOrHv82u>K)xu0g zD^+oG?ZEjLU%nT5H)DmSxtRo?;#ogf=Ql)M%iKUrlyQdj$US~SLS%gCPoRwdA=={) z8t!sp*%Zku;dxYPxUbt2Me_FS*DH*M0Y<~zY7PAn7Ecri_f4Fr{eYV|af(5GAsBZK z93<=*QK{#SzLM^=`+GI>xu_WXzEX7Y@E2y)#u0_wvcQMtIDufWuku)0Z#p^z$%Tl)K`H_qs;%TVyAY54@PVwlI zW%Mw~CJ%pG)ShHPYHgernghqzJl9I2=wk>~pM zoZa44(gvYoS^^UYONg`9XS)|Q}cj}Ty^Ped=pyc+n3mYYr|9qXN+(m4tBH zKZWbgpTE$MWM;KKUGpKgz^Bp>AmEg;DXiysC4WVWW1d`a3~xfX;Yv!5PIiwX=eRgu znWwRJtQ*yOQ`k=|4C)0Z!?D;RYrSlCh-E=p)3QK#C?AoHz2eoEg)F=5+KasY&^FRu zSKQ!GF@w`KrhT5Wim zqPbt|R{xMnJ+FH*nP8C=#=F7%dWK^j3r>6ycKy=aa2tik8ae*EpUk}5Nxy&BH@)jL zcBAaEJ4lSED+qN1Jprnu8}Ba{iRK#p)-k53*l;8ssvB*0$0#7oRU=@xfX@eRVT zd{458%%q23G`GENgKPubgto0y?)~@Q)4M>064UuwNgL9#Yx8!rhaaj2c`Ef^bA_1c literal 0 HcmV?d00001 diff --git a/uhabits-android/src/androidTest/assets/views-v19/habits/list/CheckmarkPanelView/render_offset.png b/uhabits-android/src/androidTest/assets/views-v19/habits/list/CheckmarkPanelView/render_offset.png new file mode 100644 index 0000000000000000000000000000000000000000..9abe0c353d15008f7f47bc370be713cb4400de4b GIT binary patch literal 1216 zcmeAS@N?(olHy`uVBq!ia0y~yU~B-g6FAs_q{x@0oj{7E*vT`50|;t3QaXU#a!(h> zkcv5P@7ia?hRU#ixPNlBteofC6^%_x3(qNNv|LINkjd(`@LIf}siY`~-TIjC!EKZE ztZoGTSL}=0Wx2(7t%gO)RB0=bOJb`z{WX>xS6#bt-}g_8PFlZLn}1$t$Ma7=K0dv3 zzw*2PyKbQMWP%$zSFO4g9(uLp+|G^n_E|o63k|&-8v6FNd#-ikpVO1-ZDnl?e;ztG zd2+n0jcMhQ65Y8=F0rn8{_5&#VQp>g`))^+1q&D6%#o9nm5t5Y{{GRUM+K{|T8Rq= zTRwliyXdF0SyUhQ0bcCF>H7nm;FS<5A;XFgpx!%^+*7wRut4`-l5BtAu?w{3q zG8P37UQW4mYMJPE<`esMeop^>rP|;2$K{Xn>)xl{@8n;W*4Fmu^SSCLS*lCZ>uNq9 zT0cAVewxG$R)s~sSLXKLiql^T_G)U+`M&pZH#dJ@-0`LA+|M(gF0D=ey!o^2{+-vi z{&eU0!6fi;KOfWNdSQ?y->?68^W)vaiF@UjPl?;PTi3m2=bz*G>$gR-yt?y8neDfn zgNsW~U!R`&?6ZeIet(&#@AJ=B2^b~!+fl-91dsqrODyyyd=#xLO+6<4$7zJ99P^=C3D4Mze)ZTs}; zd9ts|EMMe*%>nAz!=R(1VKe2D;EW?o_~}L99`FMD+SztCU1Cv+rj0J zjG(zy&t2=SZy#E|lm;p}22#S`@UGio@9g>`4EhYo$;sEHdXJU3+}V@=BL2GRZW$JH z>E2^o%oX$I04@LjAY(trmHnXj@_oQz-w`+qEGPjCWZOOI?>|m?{81vR^82UR(^p?I oealfNv>upXRO`vi&D&b{Gl+dY-B#8a69qED)78&qol`;+094;U#Q*>R literal 0 HcmV?d00001 diff --git a/uhabits-android/src/androidTest/assets/views-v19/habits/list/CheckmarkPanelView/render_reversed.png b/uhabits-android/src/androidTest/assets/views-v19/habits/list/CheckmarkPanelView/render_reversed.png new file mode 100644 index 0000000000000000000000000000000000000000..cf312df77da0c9ed178f119092233fec1e3981f5 GIT binary patch literal 1490 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 Q+^hsp${NVhM`j`a50670{{R30 literal 0 HcmV?d00001 diff --git a/uhabits-android/src/androidTest/assets/views-v19/habits/list/NumberPanelView/render_different_color.png b/uhabits-android/src/androidTest/assets/views-v19/habits/list/NumberPanelView/render_different_color.png new file mode 100644 index 0000000000000000000000000000000000000000..172a6434c169d8ce44fed4cd1c4912ef131d62a8 GIT binary patch literal 7389 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 literal 0 HcmV?d00001 diff --git a/uhabits-android/src/androidTest/assets/views-v19/habits/list/NumberPanelView/render_reversed.png b/uhabits-android/src/androidTest/assets/views-v19/habits/list/NumberPanelView/render_reversed.png new file mode 100644 index 0000000000000000000000000000000000000000..1d8338f2913155878658d79b14cff2020560d730 GIT binary patch literal 7380 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 literal 0 HcmV?d00001 diff --git a/uhabits-android/src/androidTest/assets/views-v19/widgets/HistoryWidget/render.png b/uhabits-android/src/androidTest/assets/views-v19/widgets/HistoryWidget/render.png index 306c49a1105920103f6da55dad77a5a472a790be..6b9a21f9425ef81bcda3257a2ffc4e6fc0099129 100644 GIT binary patch literal 36111 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ξ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 Q7=lPWmVZ?E(BReo1(6V$F#rGn literal 35673 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 literal 18921 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 VZ}Tzu2=~voZz*94Za#ec{{W&`%M$ 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 literal 15050 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 literal 10529 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 A3;+NC diff --git a/uhabits-android/src/androidTest/assets/views-v21/habits/list/CheckmarkButtonView/render_explicit_check.png b/uhabits-android/src/androidTest/assets/views-v21/habits/list/CheckmarkButtonView/render_explicit_check.png index 32c5d98cbd99eb6486729700a3fd2dfe716dabf1..f3e2d3bef893d82bc16c40c4c12ce23ca66fa097 100644 GIT binary patch delta 545 zcmX@ea*}0&aXk}*r;B4q#hkY{46}n1C60dld`HFEb&1n#yE-jyJQ9C#Dk}*<^TD=?ap^0 zzjKP_0-OxkfW!<@*#|mnw`B3(t$*7%bN{^gx9dVn=GiD)ADDgZ>~cNZ_xp;b|M~dm z&bQM^!GAMV*njN(qx>$fYKy_{tsy?EYLv|nc!gCfd5e8M7xQXLU5$Lc$-Wxv_c41_ zT-ha-)jci$`R>S(qlZ6xe<^q5->|Fd^(oKyzMG>q=l^{7HfYh!l`Hw@E^LvWq#*Bj zx_o8G)?eSAGxKc4H2 z^n`u8?ef}}-i>?yE^7UY*FGQ{bnlC)p8n4xI7Ppn)vQ5f>00S*wb}1V->v(4=Svwa7ojxV@-|b1;!=y5{idDEp1?*z$T%1>C@5!>=XP9oQ^#8 z7UWU*DyjJC(^3z%2}N!ajh~iwuuZ7@>wab57M07UJ7;l!JwLze91CV-NHH*csQ<-z XbmOTfv9sRH1}X4#^>bP0l+XkKaoz)~ delta 537 zcmX@fa*$<$aXsS?PZ!6KiaBp@+Ghs`GPHeser4NACy~D@b&QS$7x^UDJP5ek^6EmU z=dL@hvvv4H*L3^siU=skSnikS*JowrY37*Ww8fH-RrN`~rrO@`N1kt2{myc4kN)>G z4v$GHo|x#k*e5=N(B9tAj_sTeE$hF_zk4E^KH;Y9g1EizGpeh;D7o#rv+&mo*L@3r z%{^s(AmqywegURNu5i8D#Q%Sf|7rR@#rpA}(9zg^-T%Hb O0D-5gpUXO@geCwyk-!LlP!s06fLa>- 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 literal 0 HcmV?d00001 diff --git a/uhabits-android/src/androidTest/assets/views-v21/habits/list/CheckmarkPanelView/render_offset.png b/uhabits-android/src/androidTest/assets/views-v21/habits/list/CheckmarkPanelView/render_offset.png new file mode 100644 index 0000000000000000000000000000000000000000..5747014170091a6f32dbcd1bbb4f253b669eeb6a GIT binary patch literal 1265 zcmbVL{a2D_7=Cq@9i4NomK6<-xY4Q1Hd>OV(iFeYfd|b%7nZFwNjxg~Q6j0w#542b z7`gyOTlD3WoGDs@b>!%r1I6Tk3_tP%jv87i8K^Jg{TI4_c%J+D<+`u?x~``znh@sV zw9g3u0GEhx90>sIZrJ*BJGR@-U2DQJ+vSiI6cM|_R{1-AW!s()BXB>(=JJgba@sGa z_c%_kKP{^`_jST=a^x5u{H!B!;qFKYBIMxir666`BV^a3#-Uc(&%2&Ip*y&9lA1|} zRGg}k6q=lRFS^vLKU!4(QJzX^p*7@N4#?!nEo5@Sd zdgigP8BXCy7jqQ>S_IjD!I}OGF-o`|Z zVQfw*Y>K3{ZWIBbqfvw?UH3(>&@~2Mnx!xp z3Si9Tf!S990;$&bcpf7dzhc@qTy2OK(~W{WBX320f95~T*v?Zjqrl+{P~~C$YYt1U z*RxQyY1Cst2JTdUeWw7RK%m$U>D#zYM z9=^e$I+~88T!o}^C9Gcuwwg(+l@DJyOryvYXjXB~^O{pCE=yKL1mMMoBcWXJIRyLD zS3tL5e>=ux>WO-iRz(w(9PqS!^!OK?pS=4w7J{o&uY4P=(j$J*VG3Q3fPQ1!dDIQNuYS+RR`wmcte1d=c}pZqxH-uKk|9d(GZRIs=x_^VB%&y8x>n zPTB_Lue6V3Bg13Kz9a&(v$JPN_%P&*e#SV_O7qV6N*8tTn|CM~r-ns&kAP303QZ$6 zxR3A`MT(QkVVq2Fi%5LShgcCWzMgkUaJ5#Vj=>M-xm&EBkZ1mo@p;zGPE3|8*muU1 vUdc2CFK|IolK?<&M)r(C4D3Gb^OM~{`{wRw6k#0Z0wF|%5OA$Q=ZgLZDXLsa literal 0 HcmV?d00001 diff --git a/uhabits-android/src/androidTest/assets/views-v21/habits/list/CheckmarkPanelView/render_reversed.png b/uhabits-android/src/androidTest/assets/views-v21/habits/list/CheckmarkPanelView/render_reversed.png new file mode 100644 index 0000000000000000000000000000000000000000..2965eb6914a1528749fefce5b036a462f84bf80c GIT binary patch literal 1480 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 G@c#i_2`!oc literal 0 HcmV?d00001 diff --git a/uhabits-android/src/androidTest/assets/views-v21/habits/list/HabitCardView/render_selected.png b/uhabits-android/src/androidTest/assets/views-v21/habits/list/HabitCardView/render_selected.png index 63524c5fc31bb15ab14629e86c2d378d4305636e..3cb0a817fccc63e8b0d76b7c69af1f0fa1f13579 100644 GIT binary patch literal 5209 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 literal 5174 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

VF-+j0@$hDP5$ijwS=BmpR-eZz~#+iB|S# zuk%>3pJHclrW%Lf0B7gE-pxLm?(juHY5U`bxYZ^5jg+1kVN!yV%DU8!*QZ0Q7|{jR z(nASoy6467vwk~1B3&-Y$5w}%(>f@X90LI^Hvlk6?l$g6q!zeUZaB>Hpnz8f2M0r$ z6#czl`|I(O1xzClSaeVYDE+md5kAjC>tOJOp^Jg6!<4V4)l*sng3wb6cL)dez@VOp z1wH=Y13rjDAoGQQ6}16+Dh)Ka6SyE>ujh;8R(ojw+y7Q=?VC*fVAE#t(nsYey8R(R zEsn|{6fN+$mXme81W7BY&e`F!jEK05*xg=X1ekZx&(XaVA#Xc5Va*^Rz3W=&QfQ%e zLn#hGLXFOv?hbP%qkH9!(&=2=Sav#3efwQ|$pxq%Kx=^?U= zPrn|W*7N*b&XI6U*Q)d=`{E<^MJk2h>V#uJ#}%m>uj!Igi6f08&6oX;C=OCC)ol={x8>pB@FcfT)>WTFU&Fo}IAykPkJR=DsOmRxKM~z{_70CMY(vhv zPbG^v=ui%)DLJI(769NRcFibRoAc=0f!yf9oxBB_X8xBIJ{jl9xhm||O7%|<_x8U> z_BV@8=5G!)Q)E0xre;GG?BHi6D?@h6gQYgQ7jI*~@kAHc{XTM!{cU;p9@Od`z@il`^+W!2$mft5| z&BM|kTI#|d_tRHvGC+VC;*t{g!Er~Yr2LJlYIOWT9GK65;Glk28qTa36QK_(gpSy&vb zESTUbD!XDAerSoWxUBxblUI>1AoauUN}>5Y4qXO1J(7717f3&7|jMj&qdhj+?u5b!Ht4 zR$vE{;b8?+ld4+qR`^s}B_p->rhc^kF;)&8?KDnei5ieJzUB99qh?v1lp4HwwQX(R zL#wL1MpIL1!4TBKePRnU_7FS*025*$!`z~f^8qfKE;%_F4Gft3;93X=vraoYI(nkZ z>QMJN)Q%VKfCQf)Q{dvX0tzqRqMw-?G#M6>kXC+5fP|Sy21Akd4R|foTf6tKFk%gWB{8xBX{7L5>nB<^m0t;B# z%HL4YgBV0$HMH>e?{9kt2MbluH;#X!?sIPb4-`&Ln1;d9QGO#l!my_jX zWjT^kQbPJhMz<5;>`XPZ&TP3gSPpz2o?Tixa*kowRsoNPj$z?&;#K;mmw3baC0^=^ zf!)3o^j~EqC8ud99W)CH3sK!4=}@dvp^V1r(jC%7FWpv zJ5M@#-9^}VENcUFs1iM?Y-cCiCO=k6n%0%3Ea+@iU84?Ybg!9o%6q$3i0$*&(8%mh zPGtYt0(e*uke9#?k}Y=&k$tz!9hQmGkqT@gJ!50+A)1!y?RwnFA=7NAYkqJR6HObxqGhI z2$og`r?ruO8#u*#3)}#J&Qa5=ikcu49kDa+I%#Yn6#lO?L>^4i;`|74Z-v|wdE=`p zR61wUx}L}EhojDaX1iSVnSMOhe?sSJJxV|J0FUbpUU)W(Qxf~cq5UPwHv~>)sjupz#-T>a>Q7lGU4UC-X$9LC2*HH)skV?{3$eo!WtpgTQGrD|-h_5RP@U6IWEw2>j@nPNh{n%P zLJE-D$;nAM_L$ZZ>(OXXhksl1CxwLIHum-X41Iiy31wSoZ`c9;!6q75b7R;|T4=M3 zqphv2DFQjMF)^xF5OB+HOeXlLPFXe*LlxGP9k*#~`6taO|Y-x<|yyfLrq1W`%2Rf%%&o*M99# zS7{WtdpWPDHkU8RJ3dQMV`$cyCY*nGT!j8M=35B)RHFWyI6G&l4Y`v7VI&+9jE=aIi51L#CCkt z=hJOrid)C`sMX(mZhTYZ(Ye+->h3UD#bvKPp4x#i3Y{I4OTjO;=1zLV0)hl}d$8UqE?5+4DU?#W1pX3TE6F9`e} z!ShqKs1k`a`z`C33lPjj>mygq=^-guRc~}YP9W60-Bv3Zn*w>gwXTrxWDDA zT=q}zS!Ve&W)kD;+M3$*#t&_E3OS28hrJz4M=tK1rIM!Q>iBm~7gkdrDE}y_DmmM$ zq;Nk`ylC>-Qo3LRby+H+*{BDqnOsza1RF^k#6X5{TCmm?Leqf zN*DF~4g^Fm9`^aF+f^cOioi@52{E+FL|=b821foDqzF<0$fEW2=|a$hCE~U@8NACYSze1ZSXVB<#eco)zOkPQ6cc}Y!x6`=)(EEma zq#IhyT>;%{o&+hxLgyptt>0Eh94CpKhG;(7hLBW^J za}L9VqNne-D-Y*dV=k)n>#z=>>c<8~qXkv|A3%X~38b@gX@=e@a4ky4aOm13-Ho;g z(jg^6Vu9u$g$zz@YHK?wbNkv68Z=xlXjOX?Osm*r^HF}iyRky4b3v{P*LNh(JWlE_~}AK$5P&{FaSbPrb* zYRYKKSld6bf6|j)$5(ymT%SHtKC&Q!|F?z}DwI>me3dvjI5wa*9ZV8hSkm6Rmv03! zq$oIsPtKsM^8zMi1j8420BP9uWN>!O$BlA?@HsA>tq4AHykD)X+xtBy2OsLk)rN%~ zd_rpBSg*b1eiQAJf7JhxPQ~jV%Upt%Tz*C=y665w^4yQf_~b_?Jo*zeroDde6$LrP z)vs;6C`-V7u19RmC`&-sg|MHG!=0=rPoLtve*O9%5*Pf|d4-Lf<`FFcQp;yo1ACzT z(6SnyGn*sqc3#%Mu{dUH_b;301IX)vpNpdi>z7_vlb}uZ{PX{b<-U6;O&Tovr=1E% zjMt%=0M&dO`T$pIl1AYfp<LZ*nr(3PK#>+jIy2FY^NPNkZWoPrLf8zg`Ay z>{j~=d2PSGvHM2E#@X-s7tSU$7-Zs&7M7NnJmZG4Rr8_&kxPo|e0-VOkMj(k>wDw7 zo4te3jq|Z{VN_K`#k)@l?H(7Gf%VW2{ddqaV+ryoIszxLTJrgG!7uHUuB$`$>ihe7 zJ~SH**g~_SVDnqNn+|Spc|N`&;F|qhRPX8Ad~lm?yd&qa*npPk5_4`jB=+jL2q0Iq zg!)|Dgb6PkZ^_ZHQf^U^>!T&wG@e5{7_kmAE29jqN&Zv|u759NFH+Z(lnw5wyYU&J z->N$K9GZ%c=(+biKeeChRA~m-BW-=J$(8o^c-_=(r#}@!8Q)lG+lTk#d9xR!@%E{9 z+X{^TlY64S@hq2c0<_#Il!vND+6pSZGEkzax?E)Qa6rrcM*@PX>D{y27L%Lp`|i;A zDKI!PQXZnj?3I|1kf5cZaXi%)$36HnZUIR10I;JHetdTO2)aOnI>9G914J_kbPbIR z50`Dg1-LNrp!Gn>bG8ZhB#3@?+a0XpWA4y^EChx=Y7}qd<>e&-{idtnb>C6;PK#kc zsh#u~Z)bFdADp_m;5r05P8s(TTz|x%=NaSrUNb)A(I6p)+xF6V?*z^3dcElY?gYDi zS)4JpG0w7;$CXs4Bo0!J5q50ynwh-jN51Ko9aqA*ByXOVza(;>b8l+u>~p6^rc75t zg6L+tyL0QfZQHW$n~uhu$B6yA7r=64^r5Z3TBF$*M@4x1Lh-GNLlWUpH$8)t6+Z#Rb@`8j51@M9i-63Y~rZef3YWbVj!6&N!miKkD!mqD6Dr=>=~ zOy_~|0_+D~neWEI(w37~b3T%)Sz^;G=(0-omZAEZ!gZ{l8`zjP4o^Gl|Dkl=D}O}c zy_8B`+^W(2ET8Kk+fD6;PAm2cGi!3yb2+yP*&V~Z4kbeCe0^j!xZtO6)*CMYCC=(Di4Gq~yo6M}&; z{p;@L_PB3gK;(F}uv29@%k9#oOR@I+l#2Oko_P5eqYOLaoa0B}*^JitL{ZM5jwh6p>J$MazES?+@So|~CNPw6A!rWtQ z?Pr4pa^r%Sm^V0iZ}gQcje7e;txZ%_1VA5RKNx#2K!|pYC^&;wNh@wJk|sl63nmD; zLL+wInjbiH0{E0BM$4HA*LQ$hF&TOVm!Q8Wu0vJqwUdq*sJwZVF`-Fd%)Jb)uO_CZ z7ad@J26gn0oj63 z|FVFGe@OKY>K}0G6?Ao;INPaFf;lJ15_8b`!z06k7M=6Y4vxiD3{fgkpBu|3m`}#o z#(yCgM{^fiEBz&B=giax_-hu}5 zHu!pn0b$R>A5UWh_Wr|H!3VXm>jv)`wEIyK5pfp4HwYMjEOz1)L#JnG5K0t7RC!&P zBs`nO@Z>0I&kH1;Z&CeOiMhq=k`*^QrA=*biwwwh=xE@uUcKmW*&Gr^e9>_zTSfey zT#EQe1Mqx-OOSr@2j&Te*N+{pQjTylt~QF zQ*e`S_B0!D>hRN$M5afbD&_O$qa(X^gpJ*+hENRMV9>h$*p)08GVtM#Mr<{Ax1x@1 z`N38z5AFYji@Cs4=tB*&8)Y=ddhPd*dsSRqoCz^9F?sF{E%Irg)lpujq+G@I#R=s7 zF>ED*j6rLxJ~V`^M6E%GN~Tl{`#5~L1=;%S>8=`e!f8 zzyTx^IKxr3({^|=($b0WqlId8`2}|-S^De!9y^@IU~=wkD!&6_6~5ZO-PTMteXd3Rz_wn6AqGi{#RE(dkQ2Nm7|vi?G+ zowMs;uJ&F%w2QONKuDi-gFV4;`%Kj1fNHR>{{rnaLGqfocx;5s<${NAX;TAlG1C&< zuzQhHL_DaNv!9XkbKp5u(Q~#Di>oW&l;th^%MoJv7mtl_44ypsx*COMbawvZlkdYj zABaYFysM61Qg;gQ9X!gNPw?0%3z(f{3vRoNY<@X64=0?SGmIAV9~C}K>Eu%LnU+G_ zj@}_8^d4yFOC@~-`W2tkTz=IE|Jhu4ovgT$t(i@i$3^or&fPa8ANR`x<+Wx`+nouP z4{3fFo&robmu{hXdL2=Gvs!W=mFW*V@%aV5g`fFqtOOzT9{@23C=QSbQ_Cs2SMO85w=SM;@%7Z@E>HAc$a6?x!X^00|ASTT-Bt3YbIE;>L!C`I@z22$({s zZ>Cs+Zd=~qwxO6qA#A!a0X)ibnTK;%4pSfXqd9*Tv=b_O&=7g$#(UpO{QW>jzU^n*R6=UrLwq@Z{Fv&utHG*yf!{{#FF1%U zU%G}M>@lOB=cn#*j$fd1^KX&i`Jq(qd!L6VYH4}792{Q>7-CNkM4*us6M3PnJ)ZjQ z%){N?9A#C<1zGwfkk9Mj$bL6r2-Kk&3KH>BhpTdfQ75nBpvrCQ^P^i4mnZlAB;CzE z@aT7br%5f}!#tfVbAE6v=ubs^1J}>@#PonChexl46HNjGyHxSGGyKt?s}EDY63SFE zn5~#8Dvhar?H=M=UVdyzxDJy{j*0#d_zDF%=(hrQ*ev7SPut&i4T2>l zB{Q!DJvK8o=II81zNPpXptfNR4GkA`zf^M|vu(YecF{oDISXTD#Cc=zJ}%DP4$ci% z3Knp9mUkka-G^?27(g<+ZnO@-@>cUxhCyoIA5e@r$&Q=E!wY6`iw*Of(=U-6I2U7h zKkaU)uBs{fgdIUHjbiVS3H6#|y|`@T_9AC2qb4#W@6`)df4vi?)SUCqIX#vKEOuN@ z{!ew%+HCu>QfoHO#L|eGez3W5lUb7g3NP9JUH`e&D@++RVteSbLwupIlRt0)C!@0cKnq3u(Q0YPI9%%uKjS^GI&&fM_D*Z1VaFN9A@Aff^L(95SM}>cnu2qOn7)b zbMqzWF}VW$Zl>_PGvd^LhM^`WCl58LpV?vtZ%pX5Yu8kEsTDzsA%lM3ZSW3@LRGtf zazM6%b#B7U#wNG7yZat|K;=$Gro`6sNIm*P$fIs5f--WBe?vHq1nSHeYzxAd0Cislm4Z&`kC(T5T8x?4ZK zl68odB6MNB`np5Z&zP%m9t)$PTVwbJ(*NE%x%=?8%D8FH@y-O{PyEOlMDr`#N1mwH zSL!Ye9D5zN#8$R=K4X8!Wb+ zw6OroR&+$f!!!62gXD;3w_gFC2?de{+EZ^pCkN9i?$^(mPH1SzW$04g0!l-iB!s8? z*Drkn#PsfN*MiAISO$PZ!-cqQqJVBnRSGw8%2IKh_v2>(a-OK@a3M|tqXCEAuPd?u8zwp_jaDDLo8jA)E% z>W?4oZ7v=5Pt{Rl7!Hdd$ct{RDiX&yDb}AKI99wt4<^q ze7oLX@jr_D>Zq#1ZQn%*D2NCGij;szON%s0iIjA@>FzEG5fqRTknRrYP^1Ko{hoxffz0&`}gjM0gAUwawe>yfy)jJqakYdJwc8!)hOe?1%HQajruji#}`rUWiG=b zlZp=S+O3@f5mhq$#r3PG!^j!B^Z7Ei1knh{O`g)?(UGf(6T!=O8JO_uY3Dgo^eah@ z0)Kc#>m+dwUSUV$v!GwS&{M{MR}w$D4IU<iwmvJ`T6cb5j{S|qY#4$WKbk;at?nLC@;H)p3`4!@^r{gZd=_GGi#V?Fg=&tW%J z{rsyY@xS;rc-5*|>GQ87cWLZZQs*A!IbP}xO{z>ct7D>9MICNYCoU(w>KG6Iys-K1 z>Gb;PqrycS5MjHBJ$DQyUmR$9*^~ z8ui8_2syJj*gF$lo2&zinK85jha<(BthZ53-+7f2AwYoN&BbK{*p1ptU#wYLGf1N# z`iPsJj*c-gDai{Al=OtptMa@t{_O45r9yW!ey1@aGjlc?NHPW{x;Y?jcaq}cg5IX8Z79gKjDVe)xs=h$Tb!SuVxs=b=_xea~uxGm`c zxAzIog$8XQ;qMwdCMdpHG%S#CeV=s73E@zPZ(1H)4(mRp{Zm2prkTYecObbvwSLRn zZFl&$kEzMB;?$mn>b_=nN?)qNithDs-{zx^_0Zn^lh#yfV_Tn+dYV0lb>*&A8F#tY z9cQ;2_dL`E){5GPhn=+`B+kOsb!QIrg7lL|lvGq*kW!I^kDxPXR>5+0ymkUciSrOb zzzw^|OPWqhZZ)Pxe{c_s%cqNq+xUWR> zfaT(4pBe7f!Eq7b#SB--$X-Lmq~qb`)ern*@)dG&%_=zN5`(N^VTl4a{5Z7pW)FGQ zsL;NULiro}H})d0-RRaOv<+j5gTi)yf1ZWdw!8?YH|(}2^M{%F2tq>1xF~h#w`lXB zdT{+Tljo`(x%rn@csZJ)KXc3?E>w(VSy}3Jz0=F<)mz`BZd@0d_IdUVPgTlvWi3p5 zh3e#Y#{_RRUv-+SQs-?pRx2lN_n{;a!S9|g`z(5Hn?LzX_T(_x2N@AuD`Mo}SaXB~ z09jSlm~Zdx0VH+<2L2LK?y{t^0z2wY*`w{9oj)#u`eoVKf#f74TY8C!>On*JFCYMi zFYrToVOiM#2NToV`5!-sVMDd?j(n)7So#2932dDGpw3zQ(^SeTfjI$ByDm@Ta5K8}uR7=tj0X5-*k2P6b#FKima>#myv zU58#wg_e;+*Aax9+MM@Cg~xZg=Ai8MiSRq|WJH?y=K9cr>FTNL#i=;VX-8Q{kv^Q( zQ@VE7o3)hX*A-3DW+!cAW*#>!BAD<^c~<%6RLoIdWjj-7!+Nx+K57-KImk}oJ7WZy zdRWn7%4q~i$uqjl{hm3LE7e}L%+kdM!qSZx=Hm8<%56>z|G(bByz=s>X|Q*6z-a;@ z2IkZdgcDRf0Njb*<{dB|k|8dnQP7E0Kp~U~Dr>{|LG{!j{7$F|x##BQRCD5sfu3jF z+v5X&pE-i;0tM?w=pl|cK=2d;afk~?yzbN+4+uH~_LUp%69YD;#ILgUNjROKGY~&m zfM}Bm^zCD&L)m+p9>k%|--kEo)YY`V;34AK7Ew92@s(w*1-^&%qUX%RZe$Ww&YmNn{h@krhL#yyn?yYw4Gf59u$}O{D2<>50|D<%(?I*e*T! ze%2|h*~DUTQ~67$q~(P2-L=5n+S=Mz=$`_B@aINWjXGDa*G%Aa5Jf37AOt`a%KQab9D_n5C)l@xw6?161L%Xu3nlO&>Ki^^M9y5SsL2 zAZ_zb)?Rzyxf$*I_|Zg9U43Nr;&uM-Y8n^^KWCEOSB|I3Q@J9Dm9CX;uI)L~b8jl! zi-^%XdthPUBW-=plW)DwW#7N3@p?{W6GalyN6xO1y~}+!aA{ItQ~vY0oUF{ON!Qe) zvdTm0%E@Zrfxgs?x+`Q{z0mQ56Rn|zg5q6LV&XNq35YN<1hRPvZ5oA2zt^lP753n5 zxD7g3h=GNL00BY^2}as`WA#q+av4xRgH-AF&p#dt06O5ncgCfp*etKD`Kk#jqEIyG ztjQqQZ`$diWn1R{=m3mv!*4%j6ZF9#_@in2jmwqqAsg-*bkI@B$=;@%yEIp>T){*K zI6Qgd4FL^maPS?pHZt11B+bvv8aVqUE`UaNU>nczhx?|`k1{GY%3k4JoZ9jnphjr9Zom7fU>qIqd$Kdu z{1F7FGBV}~)wbZT97WI+>`f@;Z-UGSWEbOnJZiAlFcaYkf;;zlDP|==mgFFh9)Kbb zE%5veCGa;A$f;0;Y)#O_nAD*8xTUWk_^m)+Hi)Ivp?Q4|d$;e#*46~*N5ahEXJ?nB zpXd`5V*XfL>xa6ZqHSRdBsAJF1;0FIG|Au*h1Dy336Rj(jIyxnoP& zD^ZIZW%{m`_1mh~@}1=#$2#Eh^ei){e-%g+Ob{+QEM9J@!Lm=Wi)e5;+O<^#NIDQ= zzFx=2lanH#qUx1rAa-s4`0)y4T@-765?5$1U^&h{0KuqKi7f1kj;7uq&-;sik&b0Q{ zXb&Rj8FC8>7E3Dk8huZ^Ak!!^2oyLMq0jKH-(%OW|I**uN|({pB#K^PA58?+85Y%a(?0dqI2iutbv7srL?JUi?+yM>7%R=ae(C8S1|$%{Yi|13WGG( z3&uP9pXQbm#N0_QnZ0%>Q=aoQ{`IzIL)Qa!)24wZK|44L?gI-z5pa6yJtTat+H1f` z0O(YAx`_Aac|;lB_rmOKW6AtsM<~y05d?M!smO<$1UP}PZ1zFFqXU)j=&M>|&Z{qh z1|PQIwe^qR6NTKH8dxC$jp?@!y#0uS&RVbxIJ;E}98 zPe}Nfoh&Q}*rxHs*x2nX?=vuH(LuDq2DFn$v5CcXy|=U#5|t|JMFpC|zy6?@p`6+9 z>>Q8A-}Q;wthZIih?Dm6)2st^FF4kSYTlGi?hXI~QW2dkBpL4}r$x3`eeXR&y? zi;0+(0MQqM%=?j!j@P?_0$Iy50YDL7!k#1AVN~%9-1|0>ke&5Md;$oLRtw&wAZQag zfG^sDQ)=hyV^C3`xu_!#;l~OF1~Z!7-4_v}lcU#qelmVSWHBNPdDf)_`|0d)k~gQl z5_Svna`TMKw;H<81y|b6<3e`^PTK3-n;GL2ADnJ>zr<0zKk<8gL0?^sko-0N zNpbmYpYsC3b{z+)h4IcD%^q7Cvi3k@9a{s>laZg_!4NHLMI3?+kk&9C{sz!DpR%RH zDHdRfj6(JdC^DY{dRtnB8z4@LflevtgII=m&ydFK?E83s!HUi!{@^zbJt@3m4J!cL z(jo9XIKZ>y+&vCFQ2cIp9BZ?(s%mzAPR?(zBKpo}N)h1DTLJR0H54RCcNstEUa2^( za_60kSnOCefjyVx?JTTkdM8Og&$Wv_AGjQH(})Wr>^kvYJ)^*(_JvRP9v#=9Vntmw zso_6T(a{}WIN^Zc;#t^FJyU%GvbYmg5+5~r+fR6~gvgD@Z*Q&6EuEKpvbZ_T0OWik z#N|TvCl82hJE6UI1x3fAU=zB^2js+>8`77vl$nzH`ub`BQPJ<%1=KDa;Gt9?@NWSG z4(TAfp5Fv`cwzwb_yCAdHFPgSIeX&4NjDyeqrveIdB*GT!%b3z+!dKGttKQTy~>6^ zOjklb019!bM7K`y*Bu}LI;Szje>suDw)p-loTvhZtvN?vrlL<0@@9C*Ko+8um#%VfeJFqf zV-!}b;&;WX#O5?bw7Y>cKJqRKF3UR0ItniGi|@%ldF@ii=q70fni)4X!eWmFfO7(N zFvzfWMv>75d*OckX z1*sv-O;FS3OUuYqK`w~!@X!!1T=6ovl&azUzrQ}FuFirIA1y!e;-pG+vKdezHw!5&ZF)- zVPAbKS2j$tMrvhKVwILy>{G z`T7(>7CXRAfC1nfI@nF7@yLC3T%8v@3kFCFh+!Km2?ijpV0qEyunhc)c)a}lwcPML z;2;2Y&cIdw6~c)Sfe0~tR@UNS;Dc4+%7CN73=khojEQlcfI|CxaEme7B#nk={w;Gz zvo+yZ&19*ptbB_UrIXC0mk<`qG)zz1KCzKrSsYHxS#Zt$4qN*LeX43&#yui`pSyAA z=P5mgN@S;jUC&usS}KIIx<|}=*G6IQ=w{;^oto}va=FBi1M=vxib_@}iL8n#U(xY3 zydkkWG!B*21q3<>3;xo^!ST}L;$REY~AHU zOqCjdMp&G#mFLQ(+L!(G4zW#s@SD) z@9W=Ld!BYch@$Xrvk{b#!I0MVvhJF$n%Wmo*#;~_8`1~i>(!umpZSblx}p6AML2K# zQruU)>()djn0*uBiFjshusl^4LfE$^S7zi>~OdV0rO7>?{`0HQPq11a+)wATYt zxzRDQAbxghR013`>l%-l9y$SPRn!ei)NFk{J<-LL8VJ4-x&d~I26?~PSJqB(W zy?s9~OQN5|@nj@(gk1fNf3HIdPLK3$j3SDfVg&&~;?qtsTrTGKIPCE^CXqZr>^801 zO9|ZaGub2$O~{CvXXgwK5^|q3DYi5jSp4caw%hL4h}1ndOqGX;A+u;j5+dbLvB+(s za0-Ce*-Z%g+_?&&F_VfN5bfk(6FqO*9-QCB~g-Aj?r3}C+Ye3`t z1qA`6`UkXys}EY!GiAws*p)f?lc{2$epvAI#_x3F|w1v9b#t^7E z1G@J=&;V-IKhcT@ZAGC7Ev>;D$UP%Rm~#A~n85}otf7z3aUDcAN2krXuTDTt6$w%= z`VIDZEMx`*59CJ1##^M(g<^W_DX!Y`uk9Sw9o6MNgqus0N@%b>ac=z3KQh5^-H&z# z&w*oap!8Dtk0hBE^6Iv{ma>*HrxL(yCOL&1ILn{+R(d8EE)5yRrN#4Y6HcUrT@<24^qkDP8z9h7&tH0GaNJ3>`i4(Aagi;h%f z4Glh+$O}lKiWe0q493YNkAmXTq#Y(4$llh3t5sODW($$b!a^E=jq5mx0Q%Yl7aJRi zmi?kEDGlQv6kzp$OK5%)l;8+h+TR|8Em5jpnEGsN{DoaYk5}3q;`$w+~{MzYG_8^4Ba{@4&**_jeU^Q-o zM8jc1N&#i|RWaA)*fJnwP9f;4G+ofONO4>gx|T)|mqwzKh0b5R*vQ2+I~@&(4v2?Y zrrm4+hpmZ@z6?2qF>9-EU`0Tz26dVA?(20%$bSCT)fdWkVE@JRj&o1%_Nr+^< zEW;0H0m@lO$8G?CwE)sOmAuJmO_`Zkl@CwIJk@F&j#muwY)7*vN4}mzkRn|alMr$2 zoxOD-e?}=14@^-!Nz4t?BY&I+Skz;2;*Q}z*52^{NosN5!%lo+qt9=EV5zf@oKS~t z1OM2G4SSCWu&>a8J^+j%_&UE$dHbwGGw7bwF%ft=6L=EkUxU3uA6aBUhk2>NHF<+& z1H=D%;5K~&NnAqENIb|tP=}C;egX+`C+PS*kE7jH8#p>i?Csb0J{md7KrgCoY7SbH z3m8aee}B_xW2!8}5Ihv8fMqp90Qd#OzpU&woEf)ZT7lp%(C3zYCzn8AQ^OCa#o+wJ zL9~2#$6@b4#K1E7gVB0q#{I7t9qX)nn{mRtT`n!gjt*v@A1L2CbvE)UW5drPxzp2d zJ4@DC-y92R$<1QL5+w5^rH;I{{V4JG?WR>BYYmHF<}0Odkk5WA5UE4y9HsJRoL=Y6#Yr-u9Q20+tDXCnS z^|rY`46r4D&ZeiUtLv_wipplbIIYFd=g-&vK!RbZhFO1RPK4^E^fZ0^6hcBaDys9( ze|>5T?m{7fy>JJ7u=ctuafE(ckKQn8G5+HK*Rq@2@uBehbY}Dz9=*c%nVtua2-e6)$W+GBE~v2X!0-ni+a|(5_&>5P&Z}#g-rLr^=-VfJUSnnuYjR zvJ7uP>~ai$7a)RB6NQ?#g;R+})N8w78N`%wo>~SFehQcZH9kZQT?c$*cY6)(9iamz zw+(y`F8Xx|V7~b@AbMnz4;|AmbY-i%Ym>SKFH7!+2tJ|`rD~>dDG-d(kH%73PJh}I zOzn~A-P$4Ali5&638ylFTklxX&O?C&&X<`RQjatz5*x$}&VE0cG5c{rF*qVhvvA*& zG+TSB+^1KiVD8I@I?d+mh2`X%pt9N_0RxD=F#vyN<=_zI zu^h@7Sm;fxx-B3ea0sm(7X;$DLj+S#Tr@pMwipEjJZbZc?2ZD!?-0*?fUopHb2u@14G?Q@Pf6{7r*IL3J)45XMg2Bbf=>Uq&A80=6 z_f(T%Td*2{yNdb4wg8I0dGpW04A@PK4uz!Z06PaJ7vim(Er0t(zh9CidLZc_ur)@# z+7(%P&$7+g;i}oCdbLRjxjj3p@yGpDgUYJE<+*v-dG;9>t(DtIZU{Q|SmzV(nX^4@ z2$3Tv0*MGL2Q&twN!<#Y4<_i#!*a{5!$B554)V9-dkPBSz7VpL4g(B$Ov2G2$JO8~ zI6;pcdbv88Us~D^9In$l+tBX2vC-#Eh(e?WZ}{xo?NNMm3pw6O31Ye6P8f85>xW_1 zPH|OA^_g!=dC+uL`N@iktHH#VzLpHm8K8vWw&`MVlU)-4P?P}4C@noLdtZ_}bnaQ( ztQsg&?y0G%Mf#-z)W^mWXT@;k!aJB{q}G|F^>4Hgnnx59;CL5@CI`wZku*z)P#odp z<#oYD{y+~^MH=l~P;60(&_&=$xM7HlKVQ*#n)sU8K~SJfm_AExSzyN?*ZiF7YM^)Z zuq^Ke{~l(AB!PSSv}$J)Gd8yk{uDublJv&hn?|UXHvL~p;gCVJEG7c0?W(K&-tMm1 zCB>|O>>*MvcJ|dsX4O0`h{X1TfgsGqU^M1ti7PS%2L_Y?BWTef+E{}r_1ha_OsoNY zA&u-P2IPuQPF7ayvo}1#4-DbTyERcy;=mzyqAVlR0T7+z3UCX~fGD8D{|Ue=3Avcl z6eSB1YLg+qV+_Q42{j^4XufjW&S>9fUM#R~V@M9k2-XaYxtssKUsCP!P6xBH@(H3B zu0PW;sP%SF82`(L6{qjMz@Wxhu(e-q!{)}6_&3f2{BqOrd)lgZ6FB7!-b@$og>ABI z0To|}GL8;#g-Iz!{K>07fesVo;);e51)i{>NCU(5IxuxrA5;h-5fS|WObG$cDg^rF z-s#?60t5lVLKVjJ*rOF~TvDsaiuoXm1^L2#7$5f^rw7E=9UHAqh9-~F+XU|8#7S7qISSfc$6md&K#4o=RpGPH;O^R(IwcYNU;OyELh)Z@N$xNe`e70k@9NpL#B|dIYwZ8nCdV6hZ3Q(~_qq5~v~0sF>3E^2Lh;6F`WhGL>HnQ1(-3 zpJNae^{ovIye~i&c2jNwEtWijXy)eW8f(ooIv#2(4Ag`P z5XRn-5X{?g0>N}JY{^9r5AzG@^96|=JW{IJTg^**cB_PjIKDR*>?_TPULCq)Q3 z0IJx)fWGbKnF-WR*^tki_dF=*1O-CGO2`D$kox%&jJN3K*GIH@ z8HmaA@IU85twaXGo-No789}c#!uGg9AoGYHAYQEjs3Ol}KOF_E${JAj5#Vh+3tsrx zZ+v!xiP&{4{{^^^QHDc{{hAH;Txf3|n^eqT7aD8Yg8izM~fcI>&&ub30I1sio^_2=9?cPRu~o~O~Y;N8Ck zZK8cm-)rX2GsavvNe6ung^L%|YSr#ZsAt}DhCAxVW!)IqJd8bYIC?m0Y3Bb!|m~f#8 zrFvpH1btt_Cu0*Rd6B};&yN8R`&Am6vsEBJMSaG?xBAEn3lSgB-o|;1tGVA5t8Of#?UjJE z00>GHxl{{;n{UJMaO(6>gcvR&%P#*WUv<$ctxcvvQ~t4C-KmyZEjQ1%i&a>-Sl*p% z?{UYd^`Ar6-1504bKuXz2J*njPggq&JA-z}o1U39^|DrAm5OzEG)xLSgmUY;qRnrL zLRTOXe-9;i-$H1Xb8NW!!$J)O0HMnD8UXkoYY*yGv#v@)?x$~#DVc^P4Oj;T> zOuXaH21~M%H;`|yK-cGifdDQ(c2h(|#0Ny&qk*Za*J6Ef&;o$&I;yaaxd(b2bxrO^ zpixQ(e75L5T$H`RaARz0>g4a)*~@grw`plxC=pKhvXyoZ0FrM7h#LT?pK>c&_AP|6 zA6&-6HUelGJp+e^m2PfD4J2FdOP$ZuHKt{2lgU7TUq9*<_tsJFBgy%`?`DtJci%^@ z^Phi)8BM1CaH;v}+lF_?Z#oXkpNNNLoy&Jp!lDif6rbo4|9E-!(JE@AT-p&OdF1_4 z?C#rNr6m=Lc@csLQo~*oc$jO>WLTkP28Q0(={}nw(NKryNzw&CGoXGvX%1D09SS(= zb7uiOm(guDImFeetEw6o6c^9E)hjLVP6sa;gp$jhjRLR#H)3C5+zh_&9J+`ur2?rR zkcqMg0^t&`;E0$4iRYgPCJLsm$R6yJ6uvyn{QLJG^=8#C%*yly zh1=7QgnsoDm({E3%X*w$jXG}v*qJ}J%0s&k?LEmE_Y1z?KjZKC+HD}+3$2PXg8Ieq~2%_$xJ8PaiA`28v#n3mB-{OFlo2 zxNP1ZrVed3EM0x>)z5wEq!F9GJ-~jfF*Vk~Kc)Psa54}b=XMBd(b}s{49qgK;yb7WQC{g4S0swGfezRONfqz$XAm0;7`?%*oJ9Z*D$o1d=2jkmq*b#oAd{zL9FT zHr@+g2v3|FZMC0$5?B7G-(Y@`eRj7nYv)Efm$`S4(2CWfik0s2TetRFul|zDjF4U3 zx-#QR=+-{==vGrh>#oe{-LJm3GMe6p!$KPq$89tAtCuPYz5Q<~A7}a{8y`2+#>VKl ztXxja2)^@$-{h**HLEwtr+$w~FOq70-l9eBWh%q(+`l>rzxZjlrHQKQFl+qdGiy-x z!{{$QXRvhsf#*BL+}c`*1c6Md>b#tsj}agQQU|S6GPe_2hKG%dTLw1&RtU0Qm6wxS z{=<2h@Oc{+qF3+2T;c5vHBBD`U*m)ENpAtBp1n2gAxj*~B(;6ohTW)?=ff?{a5(Cq;Zr}) z#n}N|k^E!LI*t2}O+{aFZz1HyJO9Rx z(Zsz|^N;=wyQHoE?cV?e2c#M;qJo~xK5UtF6zX4>Z%lDMs8Jds3{DU;ran#b+75{f zuj2qD>v7kEBEqX&UC8rKhAh`vG`)dNgSL|IR-ml=lF-9D)ThQkDjf^12dOw+i^9va?CJ4Is851ceEwziPc|(`@Z%A;{?*5J1WgTlF zzvd&EF@nZI`oQN88Hi=OAFAxfKXZRHu5}^JjM|{ECsbgF+ahI+_l8w>8@vJMkrSttY6+g@Bnws++Fux)T%*Pri zR66XDG1&!AKnDAF8e9U><~~4Rul}mF4cH2bKmwqnt*zh!l$PuSs0#*0hlVOi@URuY z^QO6c-}|2kY_?U&(Sfcbb)(UdWaSrEzVG3?dwr$&MnS46S|segK5$3$L@43ae>f{n z+&@71I#h*u>%NS|PriF@K}M%ZO{-j`Rwc`Ww2vN);%Ec|&+e6C$wtu}CH0Zy4<9?< z*`aH4R6zcwIW0i8&!Fpzgapb(c=XvY16nL>ZP}ssK9z_*nuPlQzxGNvL0D4<;Mos= zk8%JT+ysbDRKWO&p2>A7>=Q90OAPF$1(#S<&>YVgXIW>dj;V}UWf|X_Ze$v*+DrI8 z)Ig!05H58?#i4@6XI<*1b(Flz%bEfPmUj)AS+iBsqMC_2^@p4PXOl#4=K26vQ%cM} z=NIR^hc5eLz5)F)>7%@3jxSwbTCDw!W{cKh5KZ*GpfD$Os4$O@7bo}WI*eWyVgwscCvCL3KJoM^xHX5LOg>8B@4z`QToRZ zRKS_}S3g8&N##E=*NNn_j#>o2TKKMRW8PyR;-ddX&km-C)E(O$+b&N{8e7pSzOp^% z8%4|irJZ3Xxpj9U-Ix;8wa0`K?=3=gqf*lY)5EKqOKVE!$G&90Yt+OPkE#n;+CA%N z>cIz99P>%Y>}h9r_YX`a(Ob!VdEmp&6S=;4ca;(6URq{@)k^ z{-p^g_^QGPjCE)8>)u@X!E5kOJi2%cU3`4@JOPK`aih@C$2lAN56GD%@8U-Avi`qm z{3lTVmCC=HV&&&g$z(CVraBO_5(2UZ`EEDSDP<*UK`FpPkL>L1)c6jsz|x5Y@l~E) zg(YgLd{?GBzjCRT@XV^&|3fxD0T}d-NyBJR{ zKC!U1585`b%Pe`YWS`xea!BC?sNGulglM53PHuSag&wm!(+kvjYZ(tdKdas4f2;ZW zT;z(})Z5hBdj6N3F4&K6U0REsQrBwA{0NhfHo#t`TtYzO^o7>r|A7>8Y&A07N?J_Y_c z6s}Nyb93`5+VtDBR0A__B4IiTqeQf)_r%>Zp*_dlrcn>drWJYTsl{)0#9S={mF=@Ox8fIq!UO~^;Ow^}aOY8m~G z#%;%5>Ykfpdy<*;j`-fCeht~COcRhQ(SvaM76j#3?d?J+oiD%};Rjm_)35hxV0?~k z_pHM+$Y_*1_)*LTJt+Ls(1u?qVPHXX@}2Xo%<}T`FEBr=6*|zge`KT)Qz*qKN2*NyVVyhw=02n1q3WC+>ve(w2 zj3T012K$vNzqAQGPIxE4gm~pL3EA6b+)QA^rJT=E)_Y?E1@km6?WWJ-JG}oOw@z&wF<07Zo1#4`eIZZ_o3dB7AVg((=5c?8T))x75k znC#hp{PAFiJ1T@LaG0Uug#pste^mF=i46Qpa}HezWNAqwFcTMsfu|nB2)f8Kk=@Tg zZ(oP}zGleIPb5GtFw@#6^T1Fi^yJG2qt@t}5PaVh;A%8Oce?N3zMB3=H!ZK=9Xkc> z$-lJJ?<)Tb!rLSw^%o~86E-(x|1qg=mjE_`NZk(2h)~7l;%N%BBvd8U5TD{VceUn2 z!%Mwm4!jPCu>$>D)g%n1>uJmk3oad&v_$7;!osdYuSXC1RJ9|#{ikkUuk4coKiA1d z%S(Jwn#=QwAO$#pAOq9R}b;DAg~GZ?wIHxMhMTWeDYezOk^&^R0+{(9$r zPRkYE`3zzZUcmWNd*)xeA1UJ?{y@H&VER83r*%1L7l&bB_=rEeHPonCa0jN{B*IGq z#<*AQhB@jV`~xg>3oAe4<~1LCJ2cAb2PTulVI|TQtLEhBru;4;mIq_BZvqoyTIs!OwT{)fB&nfXVgmBs%rq zNp$7x?(e(C>GK)+nfPM4CnZrf_o1g1yof-;Y(|#*G@$xnKnh#KaF-;Q!mB+Fe3v7{ z`-#Gn>%9)RcjL~Ei0lo@IweE*4SFWdG^3V+(gA2ZWFr}p-6 zkwOyJP7OA!JV1F8KNt|8LqT7lCsCD6odBlgU4Qnirzfo5@9gv(^afoETe|x`qB2TK z178OR9rl51e*@ygOIXO_@-jC%dK@6CaxJ#U@C6X##C+0|oK?`vI|a9#2=Ry8WIeRI6ya%q1Gp z-pcawuZH&a&FF~o3RvB)&Z<+>)(4ThMV1g&LsldOJhy4)d|YXSWVut15Za8+2HAW%+K; zevkGe-yyNO4P8$Z&4dU2oTK!d!7ne8-^rImX37O_GAz;9y4r4B7bPsxEuKBbnkSDM zyv+0Axd_f$oT-G7@Lf%Ap~ zn3zt1za6lLu!Tmek)o$-bAVAkM2{NqgW+P7mJ_f>?<%DUdkPzU#M1}q2_sUl9bX;5 zxoD1#==&!OV4+W!Ama3=9)wsB0EY`9g@3FERAOiUrqa*u?MPID9`E{+35Dt8_Sse? zfBEYt0X}%qbED5%``|ft%{pYAK8-Wv?YaIsQu~5yis1h4vb)G(3IUa2JuFgG+Qoe5 z0Va_N<&9w_G4+>Mx#)c1A;pE}JY^V8JW-pkoNk~F(Q#hs=}rk0GffPd52dwp(1fua>ObiHL+Lsc<=N=AI> z|3(ESm8$A$%G*~i+y#q(aM_}b{i_3pV&<&}qf|@j&Hp0CA6(G>VgO1u|4*H#zVsqO zOGLG-JVVzDXGdrU-MFi3>ppa)49iW{{VOwHxcvDnWL=IZ^x4KqxTtvwy&rlo>M&$r zh@L}UgonGrbop1e!3?|#-phIjpn8NLLPA2DP#6k-0>B3liXTDuZlFM*^~d9QWg-8p zhhY2~Z0;`{;Q?C!nW_W8l?fp3I-WBAXv9SW?G+?C=DO3s>4)Y26QV3CX$&=t`q%jF zz6-=bR1KJ<>|j=24KsJLa27PTDG3wfvS2YkSwcygF;VpmEy!Af%Z{Z6?uB05j zo@5q}s%H-8u2|S=PEnrwC)yw1MDyqNV!9YNX32JNpcY-QJ;*ZV@O@VgFCpSe_sJt} z?~@vt`P^EWKih#lqZ1^!oG^T^)^5EC9N_}%P}~TyfT|fy@B+TLj36M3ya?!f1SA)K zg0KE+YGqabskPO}+s&<3C4G;=CQwEEAAx}rFcOGK$;kBh40{Scra}zBiD2`-4kXMZ zaPEM@-hzWe<9j8geR7r1KdSUYyLT9Iba1RfP><8xY(^e6Pd%X&m0@`O;uAKT-5@wz z6&0*68X#NUTjY|Im$xks2R~XrttA{O8cAbkcS^_*ZV)5-mhU%teG%ajT@H3DuPo=c^=b!%2A zV+d!!N6>*%x7_T}6O*sNer#u9;lbejaQ;{9IP|3q+=(_YQq}zo5S4CJ`I5bQxH=UD z154LAVP2jOGE#GVmPYI1@eS=PIut;Cx#exz>xIp90Q4CzP ze{|ku2u*r6Bt0+8BX=XpPH$L-eu(38TD$YzOQG z(cf%pZ?+VZ_=DT)YS^cu?Rb7qrW5K;SU#hJ7QC#`p+oMFb!=2rdDdP67#v$+kB$W{ zMt>YgGzMT@*TLDh6$a3X*x=|WHF#T&!ST0%4sBEpN*NM^Ck+?V|0m#lfxhc=PKrO; zlm`+yKF^|#&Iu~{>J003aE)?hy{nR`lr)OoH#uY;ImBL@mp|1`Smr#}u6@{AJJT1X zn}{3iav!hu(o;giTa?XZUrawuSp?6yMEOe=?uqitpJLi1)+i$~xXszrmu^NNi z0hJgY)UXV((n{#KU=XL7_fztiy|e~xs;P|3b8#glr3rYbDFEVzks5yaMMZMZg+rvI z3t%h#XwUt6cBH5m$XLq3n4tkOeG(*NuZkKL6AZqVVg;;B8VnWecjbqhG+sqG0Hb3|FE&9J!+Ds3&mRw21-tilyFp ze#7ZCS-7-uU3K-9_3;{3rAP0kG`5%QH-)fQvzYB9+8HOI(^JOI%fG z)^|Au;yo!z(31GRpPW+2Rf(jJ?nJFHC*|=04Hl!t=BD{5_BI{y3nVe!?9GUFpO&7} zL(%lgYu9a8xLtA!^B1m@G&rv za?_@`F04PFaL{k?syfKtMtf0g+PamTpi&q(r*AyBqF& zzyJQ9arV7?pL@m~=Q;-8H;5PB^{nTa^H*~PD?XLFic5}*AjnneCz8qtf)<2MLGi%3g8P<8vfI_9dOVs?VPY3uR?{UyR>;!lrmccCDB2hMvef_XmE$Y#c>`;dSmsy_yt@IPmpf+135maK@fL#i9FF zDrEU^ExQ0-8aW_=3EzC9mf;6K-Hm$_bwye!=sk zSy|WKb-c@$ujT63jd!)S29FR`Tr+IX@QZxh*4cTk#TIjMC#LPT@}a{t z9`_P@x^9)rp4G4I#Kgq0zP6$vD;4~po@DfI>{C-yhA+hp2oS@Vtn`HRPpIGo@~rPniG73aX+8^JW4^-{(Et; z6$WzW&YeBt_)iiN5|URFEYT1~Mn)SAjabcxF+Hho-r(SQKmBc4Ws75RR|uU>=vGWy z8!j%c&6C^L_07x{6lG=GHg{{gyu2zynhg0FqFS+&-?ti9#Kpy_n|3AEoYlX?a9`H2?w^SDe)y&ocHiQa zs8(Y}1_o+uggU~k#Bv}{FF(Z9-u^PC->X-z;*~Rt7oQcjgj1~un{|HP3l9(16`%~q zM6i%FxHsNyA6bK_MZMf+8iQ}F@v_Fp#Z?r0pX}4%Tta6=Sdd9O0YfRN7PbkmoemGS z80I|7Dv6XoPiYBxNP;E%c6jLD{nCR^7IuzGm-*OYEbkHGe8Ri*YCbJ3txt*sHq$h` zhp+@8=i^^Lete0pbVCd_k4{Z(Y;4Y4)<-M0Ptq|7#vBs+WWb&$;48uibh~ z+1lPt*)r#F=jF?nQ%JaZ$bGLvJ9g0|+pEas%a>ak4eb+ri%nPhbJu?U{AtETdPPlB zQ?oga+w9zSq}2NI`T6UW8Ray1GK)r^g2b3U~(+_@uPP*k*X1(}!ku^bI+W3Ch4Bi-GF!bx3a zsNY=dywcxcvv^EV1bdO?aahvNPb_%bkK4MsCTQP1@oH;p2%*n|aR#Q`(9~l`T5VN0dJV8T4GeQjdvYx4!btQVMP-$yvk>4T0 zO_+6XZ&>X9%D6UBCssCJxeosu>FCHMKu&ji6fWX;EdD;5JkqJJa9r3g&|pz|^ytz0 zhkGh%ux_kX^WTH;sg{SzY$pVfSmjI}-P_k|^o#TvqRxKLY~{elzn+tuYu3LS8WMu* zzEN}V5kp)@XEdUrp`prhKZ1h4(*`Kz8q@;X~Pq7myzq&ujBWg`(5%IDl)TumZ^%1EcWMWlQ^GzH);E!$?_2gfueYkp(}zU z>(}|TPzb%es3gM0>`W57I6K-|;J1PulAad(_U&8a$)j2d5w`;EhyOZGY)~kLenRC# z3SRVO6`!7-)}c)%weFJS;T%u;6JWtU`zVvDe0n$&fsN+(bIP2B7A~FY{79+9aiP=k zlOaB(K%}~!UgA{*>T~C^3kgZg$K@p7!>OQ{^_h$Z&n~hp%QG@ER{#9@gOQSwf<51r zU^(*d=gq4W5>7AY#ou&hM2I7_Y;5c16SdwWS&TiN2kYLK5EfQe z&Ahz46eKb!DXG}B}l9A6kvSZ=DixeXX5a`HLzn|5^zHj;sit zgsAQ`lK#fHAgP*fjr&&?jngd5uHk>C5^Bq-tn^fnXSfU=lD;bJbGh(im3~t zA%j+Y1V~m^mho^kwJsdKfP=SW+_fB>oJ#tbsqfq7nj9*sHByx`2dzpk2mQ?4VJc9! zXs@M{B!O0$@SH>MlKYL_69a#vnXZnVs0 zZTM^5>9%aR(ERpX+pUo@TQTYQJ$};(!Y_EL;%~-t^y|(i=R4xDIZ3aqm)p-^-6aYU zyK_C51{tmMy;xnz`TG6)cN`>Ej=^^J*E?SkkKK%I=Q8%FR@|2h2VRFqM{&0q8DlKB zxQa_*BiY@!aYGmpa9-}6*Q@cM`aAbe4d}-FB+2Np)1x4EzqPeh`Vs=|sPhKnQ&ojT z^*rse^~sf-Tio0`)Cio?s4xnC7mHu}G-5tp1PJLBEYGHpn^<*nW8>rFkIo#8jg57v zo@;fzfG%1ldqJ&NJ-P3jXwxNR zqxK|Ef9-s8)6O1VnN7o>dBUUTy<+?CyI4amh%fyHz*Up?kQ_J7Wa76}-EqZ2p zdwYK(w1haHzkK~VU^80IDLzI+P0jXHM&{VyPx1pt?NX~F7cZ|Gb{)?(PexzJIKER+OD>sZBsYkmxan*sTF* zSw4p)mp@-Co2b;(()x~$ff0b}g$FG(zE;<91K5^H@$f=P^4@3Jo`ntZzg|Qi3w}y2 z@6BJLoXKKVsBx|2B|pTov@ z4fj=DQ86+7=eD+DVo+VA_T=q#*aqHrEsSu*$>qs0w8=|L4?%C-vsfee6-vVXF`SHh zey1gZCP^(*H5wsBfyf2}yHsV1(2I>opYk1dSrc_3u^y4cYigUE=i0F035OG zu5`APLY~OWdkb0i=L{UndjAZ(TI92k;OZqniO+cF&YY62YY_hjsDG`a6^SvG=$fLUvB>MOJ)yiRCs6Us>u&cg)wRP}b77dh+Cr`Qo1xHo($10f$zmcUW@qZB*}s zJ6E}^Sph)WSxry!@%Y<&l)<|gg=dX4+V1ynMbNz zZDA`2ALNX&#k4V_Dwb=G@sQBa zq%bIj5*?+0R?DCiZV1DbJg7TAUP*(xi|cK5;tVyI;Yo_(T{Y;h{9IgIHxNLr+ylAV z>YQG%Nkm0ObCJ&&ewS}B6wlZRj2<2yLIZ8qx#S11L6nu5IVyrm*u}}*+?>{r2myFf z6ID{;yaV;`1c=bn%XoNrP>o*b>5KaK_%L8#rSi>TB~hgQ!KLmhdo7_}k7ZDk`miQ)T^M9KhE6-Z$44BLyhVTL!j5IsEy+-jckI zc>cPZG&C3Edn*I!w;341C(3N~V>MWOa&1ph{FOR_5l}#fimzV=5b5)9nN*36o|}O1 z@sZ5|ec!PhGGW{C>XDl_Z>ACx6T2*z>ieGU?Z3HptH0QCVErOZAt`ZJ=m@C?08i4e zu+tPoKqIVgZK#4w+Qy=Mt^Sn2&{*$zrVk0pH7fRqIim;DgaI5PoF+% zIW70L@-i?qTW(G^2rmoUdVvl=57h0^r{m-OHOrp{9Ew_6TFEvya0Ai+GHIS*U?Wf% zWLQ~Ptjd<^Gk7R}@1<0rNkyAFLznk0X|S5Ty$?7y(Ycouh)Ds z6Coz5$`t+kQ@RD8%_!+4Fzu9r0uIaV*;b00ni_uSP^J%ke9mt$GNyk7?ZYTp$OSrG zN@r)MsJpv68DN!l4>*oj&rS~XLugzQkA!WNi8$2S7LIV=*x1T z4w%cOz#?d|{9mG2V&rkWv7DUT7QiJ1ba9YnpuZ+1=~Dp29tHe56&o9Ch&*}vl zjr~G7Q`HXoMGs$Du69|eE0mVj&Q2f29imGhB~-r88-Gj1faa!;p=MI$sh59UYz0lKlo1mA3;h=LodqjEpDt z$Gc0HkjN*u-#5?q5E*ru7P()+@_!c>=YH`c054rxS$P`plI+^*stBLeActza^L0aW ztos3&h#bQW*rl20Ws>xTQEhW`>+9?9uTt=-`jP@;41@~^k))TMJQ8$-MwkuN=Ev~C z4N4)W41?3dt!xvnxa(RP-;Je1H#ax+xZ-lmx2Bt}*7kzPmPKCK-X6!D;O*u0DpAz? z(>`>@^X}d`p zdPWWwA%)m}u-f^T@$oOs$iJW! zGve3akF5=#5J$E0kipw+w$-)bi^oHN3=+f2&_%WW=4rAxx#}}qY|$~{xlxk>t5E2^ zGmin~k|ks4q6=G6cS4d3QB+p`I~jkQ5&FA2^iYuIyvwIF>xM)`MBJe1(M+zcj)H(x z2$&0&F~^uIj`HDrx2h3=h?oQDaz0a`e>Una62**~-;Tf`MuXDol8P?zHsJx@FQ`T} zz%g*~@OIF|y&GwxW$+>>1sx=MxBwPDLn5Q1RL~GBK5a7^E)+652ec(sFl4ol>iYRw zCCjO8_p*Wdd5KQ+_Vq<;d%jBiIkgGrmq}2tV!W!|au^^&MnFJ7f(~0uN0OLtBaj3A zMJNN)+GRH0IN2s zZCi^FkZaj^czH{FF3t`TEJgJio0|h!32_=>pOvS$USW=wd8Vf~o?WZUH0Mx}1ADV| zJ=)@p*u`m4dR?8bqKwS%XaF-ccCMu$>fs>J!?Os&HW>Bs(`RLF5CGZ8+;IhE^m(MTlbD!T)ZpOYbLg-gjt&lg8Rb7Y zJsXROj@|=-!fqg6pGMEK;%5-S!TIJ-g6t%c4+#lp@SRQg&P1W<=qFxFFHa~)>GQ8o zvdb$g9RPxHD1(}iAnJX5m>u#IXbU+4Kk!w)V;>aS5)>eSPLGvjN-F3u>nc6Dt4ZxmXyU960kfcJwI^mD4Bs>-vknx+N*H3H4WKy1b;pVcINkV$>jU{CNN8B}acP79}2h0)cqD+I?p_oJMTCv#+mj1Ik-F zz%3^V3JN^vJmLWobQ1suA0@07^AEx|qX4r0Rbn9?(W!Q`chJ%rzK`YK0M%-f7&l-Z z)w6hM@MGV-+p2GCW1a-|M#c@ApElHrwfXse30lHf3?!**U}TBHi1b9W$W#~FohP=o zwsslpd3yl3vU7FMpW@=qCP4nbWo2zWhAPlV@|Q1PSb#CEf-<9!X@nvfxw*N% zWc)TdudAx6>VkrT#1IkBeHMU7V=d4Q4;G!bQNRTafiA+VudmN6&q;|Ngh?yN%9^{q zl3zE@4dn+7j#I9#uC6x5MM7ChaOXmd8M{WoWQ?HW{BB8Mp}jTiepUo-@*@wA<1n~Z zsw^^;0QwWe*GU0k;WAttoJAZ26BAS6`i&d;F3Y`{L8+;!CAAK`9}AO&oR`;mE&F#} zot&(mTUxGQiPV+N!krBM`Z(-Zc4Y6m;S(Wma$BQEKxv9?C&roB*%eBCFV1t+6KH6l zKu722=QoX2xrXX3bPrc@I4vqN!-;F{Nmpp=J-8i75&$I2V|Vd6EaeuMAfnPwpXTl8 z_$VqyW`HbP3c!g)N#Pp>vv-&`>T5uVOC2h7D&Q|L${)QIkkETD)8iJFg))dZWytYx z&Vcj$7bekvM=PCN7(EOOk`>ig{sv{M=gXkYblo_#&1wb1rd?) zwQJY9D?!D!0?B${H$fYA>>9v>p3e4mIUPMcw)?K@I@54xdX}~G=<=o2DLbhCG^AqO zM#uZ0`e9PWLqvIJ-STY-krsXXEuwx2X4F>=hfPFS+{`mn^;`cKoeB*LVbSJJ(j`XU z@3F|q>nmGJqdpk$ju?&`N{O~^6B=+_UMH)WH8V2$d49UnRg;jAkc(sh|JjB@VUME2 z&pd`EDe_uzpTL>7mI@>9>uG9A^;f*>1SlnbPl%>;XQ3;}(AIXMu)12r5-#M%UffKc zZj~q;+{HEkkISWH;~uh{#=jzGpf!$Y2CbmmulbBwH!X9Y}{WQsAT^!`f%#S(kp^} zxx5|!3c5o1Xfu@v&xhk*$7(94zjmrD>kOn8C*F;US>dSzPjUDup;-MSrt$9&_e3$Uu8^{V^$;s(>R(!C-1=V8)ANMTdrnOStdb|} z?D-F%-^bb8+n)fBp*}o0sRAD_!o}V`c(B^tv2(UH>HsawQ@)Zz)Qx4_LYOiFkLDJW z599j$w=a*l+2vL_sQtaLX|wO*DQyX(A>(|koY^Ccidi2Hw|;b$f2PJ}w^V>1Lc2BL zfgRVRdC0rO|FG`$i$Kbm%0uD9=Y~OBn`H+WK~3G7IeEOsBl7pxuewK|`$^tKLq1oy z5?7?Uv*+eZC}sAXf^jx02y0G<5J^i*lYnCP7eyBa1_oLuChAbN@#GA;-!qjoIq5%3 zffIIE7X_9*X<+~^E#g2%iv94xiS6#)jC>82yc3N*8fXz*fV@}S;^aQIE$qZE2`fMi z$4OPb7xDJ(sStGRy`=fxJF*{t(bLnLdU|*SB7@lG7oVI=A~(cUnV1SEH|a-PD=?7q zC`atMZ3mX6oja9ofzK`+_V?E@*+N6lr0Wb%qVFR0Yw50vO3#8HUDHnvQa@l|rVXTq zs~&u}va>OH4dT+;S+1~b-ClPY{)dJ@1z_*FWO#vla_sl)G zz4t*CKAQ*M^FIE;AHifi6c_r%ujNgf5`1KlWq65KrR}P)vGfGV7Mg-iqjVA^) zZCc;oxpCxG`^?E{H|x!tH$%tmoGdKupMFlg0mhcpdzTvVgBR%pzj>o*pILA^_U|l! zz~^PLnXEO-znBy~rUittw`wMp_Sn;g1F%VwU*V?lKGoE~X-7jcD+u)7$h)1M9!OXj zrY*c(G5y8q6FrDs_@>sG=;*H(Qm=T?AQaqJ5@=O*ucansLkTJ1a8I;7E|T(S%VtPX zG{-^!u5{&$@w={%YWrhd{XMsH#DMZKpv8uOz~EF^Qc|K>W;3<~3~wRJ2z7K{iqgu9$7$A-|Y>LedNt;p&4hmpuN{6?2fpewEV; z|D7e{I69?%2lK+SwSMdsRin(BNRXkf2}_ zS_T^}uw8oam-`tQ7|;>3i(qGaJG)Jt8jq4VNqTz#Tmb;LZ7nR83e3Cd^8v!icXxLO z)=f)bznx~vQHK?r+glqs@CTb{36zfmN0o&hFgxgw$kVjNNsFi zdwXMXribE8`{1FTg(&RQfcR8A(bYpVrYxoc{^v;zJ3OVF=laHPXYkE^;LuhClUgz0 z)yWU4-(Sjqg{%H|rf_#~d-*GyE|_=_-5s1g zA3eh)ra8m4Uka@I(-_-)=o`%$?x_oVlF;sw0jEa!C;O|e4(k&1k#J)9i(T=5kkrgi zMNOD4@x*|`dw+W8NEk)jL{WhJ1f<7mzya4lQ6x|R8{8UXLVk*>u*Jp2D4-c0R}k2J zA%G?r-%<(pYtz4bLVkh!DNt$RiGay(A{tlMgEwHH&qe_K$WLpZ+vyS`z`cB#44kHI zI1zOz_Z%}7qy`A(2+nXSQY+YXsqf9=a%Qij7Z7XGP1)1$Gg8$bofH~y55@MoYI+gPbUlFHF-HY|rBPI-ujJD9Y>>rfI9fwR|hG zY{JJA0xMa=0H^2E+KoV#V#U5n&Z7dZ1}KypBcQ*S_SLEOm|HLS2h=P)%!@R#-&J?h zIh+kRzn8$!FwsCzmA~dbHGF}yp?CP@z{_iVhFfk}xX<8-yp8lCpF7Pyf8#zb()8Vs zs4Ya_yzOo~T=PQrKso{7fk}`4t2ML#)D6T2tv>K7#qjRxP|-i?6w2TOk$kng?eT=- zV{LIh+i{UmFlK79vSa`^_ExB**B;K#Z@H<#EgaL)()!c~YuWe19gR>(0# zd4g_k3+hGWmwap9kD-lZZO5!=5gk8&+zRE@J0BdcpdwV3U|wc-KM6ty(!g4BVdENm?yt7y4)J>* z?|uXMz|0H8VH#dgFjKR$nfX~+<;(a}svF+!6A}A2C=%VgIR+jz8R&+8KV6`qEMc{0 z&!p!Zs3yX-9)iq22kOVdj+@91=*(VqKtkG%ht-TULvsqgTyQz=y_r9TV3oo@fo-gV3D+D@Xl z68bw-f4N7^&8>V7=#VIon=Nzsv$~6O&ss3KO$s$~>g&Zhk-O0{m?*yf_3XM0&f}A5 z6lq23(d50sy$WJxX2t_ZoiY+vO#V3`LH;9)CYL@0YZ{xH9(BT-|4>`nr-2@RS#4Jz zi!pTmkj?Z~_^61MnN@R9%ckq*Prv@NP0#IyWf#B~we% zm@u$f%2C#_`->*tmCd!F8?H~)%Hp>={&e$Rl8L?!waNJ-Ly>`2$0wCdnvPRdy z0HaYaLS;p4pduMo=&(UjW0V`Y3-qP5sK~#ruI`rKvS$-WcateajpGPxs87S-pPB_X zO%ns3i~yf-4P}V^^>>F*hOcA8D@;!Lclz>pp6q@R*393;JTFN(O0_Q^FUfM=)4V6( zb8>tC_G&Sm|4%^v%=vGe7ym4f>XN zg}Q7}RkWz6sI2Z_+*3E6*K*zps9oB6luT+D2$E03z_I*Nxz@&BSG}^Z;EHA zJrT%W+^zE1TOI-d-?`iU)#DJQnT3MpoVy$xiWktS z?N+33VQ=+`hbPY^PCeVdFC{&GYGKK^B% z|AYQDq2cKNN2+%B1~9>kA|BD-ufzWdBtA0h`r)BMonf}>j=sAormM2BBwW-nnAS1d zr`&(r8vCu7!em{=dtZJC)BXS8jCK$8xKYf2-oGCj7UumSGEz~aid{rxl;QU6#_T*3 zQ0cw&k}CGr$42rLl0?^_ST_Pk`3nm5o%Qh=;oQQ)<4N;%KYTVS+G`rg-@aUe)BNs} ztG-cALL945h4U)_BAQJ@0^SEazh~zHWlGf8T+B^IzIUFhxOS0pP;}6v(_5)frxJ;F z`m*%&P7G&8TPR$NhhKkJA#G7nJl!5v6lZ@hok*sg$hul1={>PLFseg4Z+6r8<9cm5 zf3BjIhRLExSjWFzTQmcx9S63fW(E8!587nue1horQu;kmS=K%QMfP0>0mh| zLP#OA=t5bmi{YM4E@h3pR8aW#6$b)`@0_-#=dJs3LA>4^`P4;B8QHcm#8wRPsWued z_OZ*;39_zYA)kF(HMT#C8Ru<8?)#6}4Srr0kqWHsF`e7UHjKDU+4|QtvDpgTy>Sq3 z*DoVr;E4%BpfAi<{4%1Ws|$_xDOKytmKXl?|Dn;|bFWQ}>K+#XY7)`Ms;5s!JER|ln(D<4J{Q3{!WUOlBK|V%ijGve zy*6}cA%N!5oHp1|ezuD*F(y2dP!?!p-zZUC=17?sO|~Ce^gol)J@vc0T#e4lOA|lm ze^S#F+ZWjvJue!}7wM=nZ;UygI=`(V{<`==fPd)ovDabm_#%^f_p8!E%K z&aJ^C^j2!opTzJ3(+(TbiZ?LQjEk@6iGzPI1KeI~eqn(TB994pxVX#A#Gxx9zI22* zkn03xF9=+*D&vQ9OKWRXDXL6!pnK{|J$jT$priu#fIjrio7go-L!uk}vugiqW=j$| zh4!=Fm}6^giMKC3@IAK*?KK&~sWH4;BjNS1fX6b=ZUs-eqa6Xszb*2VXR(ymy)9Rl zd%!fWW8HYXRV3Ph!CKs)?ju`=P7ZIA%fVXz7a7geL&Jj@&O%qVSq$;j1iYiUXyv2y zGttW{lS2(;etNi19&US8{ZzCC>GW`_ab8x*%vJP~-wofS_Ci9f*h`*R6$&f&`^-A? z+y{2wEyPQLT^ihE7>_dMy!QIk$ra==FI_qW`y?9VWpW`gBcn~}UC50#%7Zs20UyM$ zaWq3M6OzD%s!Sa@N`wdk+_3^(ylKkr_0_OG?EhfGGea}W z((#zspb_chP;S3AGv9tP`uexIV+z=mm;=BKAa-@IO{BO6^ z!&<8Sm0!*qiEl+p9_`$|ju2=Qq`YCAT_9e#nH?H5yrGV7nxV>so6f7htRLct3sG(%3kQg^78!x0i&Pdi{zYgvgTkc+_YTKh7ra9OsdrjOL8i zBN%ayF7DT`&R%}U=zYY~-LV>Bg zbi`X$PL{sxCanM9}EH1UP!V+T(|0XC~E!||MhLxEG@Rp$C2)i5m5r+9*!(XC*+!1O;NrjL-(fse zcKM{>#iR_&Y7L^aVg0j`F8let-p|>Eo?@#t{fOP^#tnHDOv}uStPCDr&K|dMJ-s{m z(}fj}?H`${7!?hzqICONuy=rxWB0E*Iy=u*mX{Z!LTL&7wtDDMtzJ_*++1AWA=>L| z0G8W6d;Qc*_rJpE$J3{ zuTOSq$J@!f;RZxQ+9GFIN#IT`=QBzgOv9K zf)5zam~QT`k9nQ~4!~UAhvOtga`Wb#mZqj4RFtloc`ndi82PP-cS(_ukPsqRlcxw0 zEJ@!zk=;x6^`f8i`H$C^QAwgPfZX?;wV@WBA5Vv}_iJcsV#<9MC^P|y*4lev3*HVk zco1)6T8)oD_MJ%1*6?0jB!9J(LPJ-^bC4?Qc5r+3AqBQCh#R;dsYjl#UOQbo`_spL z1veV~dlv4)^w1P-srm<25!wnD!f#J*5YRfzM&LNu1ogX!mM1#@oOHJ^(%2jc-*BNG z%gd`Y*13YYc7}q-WQD!HUYhASOTrK;488O`;A~J zkfyZ~H2;$vCzJa91>`g)U=J2|TFz6zdCFb$DkwPc`gPNRCHx#W0xzlhkMFq;OMk+c zUkDRfAa-?FS7nD}fvo2#;mIvkrkmS5I*+q$o4!wzgkU4aM5dFcXFH(rm4>5XbxBi< zc~xm$m`%2K;zmmpPM76(>H0bqeam!I9=TD)ZY0&-$@~o0{h8~8O)i5I4asWHXp4PU zK+OPjo~$QYs{Or!qwiD1lDdGWl>DBXZ`u4m1oW-R(Xz@*tB_7kCu6j3^et-Az;!otgI_0MpY)JhF_AJKl zOPJ+YZ%D4{4@P$w7uB6PI?Fjtcdw>(W|s2$=2qQTQK9;#~M#;zlpN$wK67s+Xdw(-Gj>;ir>pCSQx0(7&^ibb@XE?8}f8AlSh;x zX?u|HxPe5r%>~wEN_V|I#xVxt-XHws5+Bg3pO>5fQpQAn8GkqQwiW|=-~a`5$6X}x z2&O=4^+5?Y(QRDzFZqSbe9Z1IN!!4mUfWc0lJE0FR{GIpw)@p@cMgo`az7XrOzhyb zJ{`Yr^2RB<25@0%M7X3|C^h?@=DDN)bES&$Kn+Hn_zE1gnzHZl_a;7E%(N!4uh$j~ z2;@oi)0PROZbZMNLIOYz$uy3ceSV zx`DmKax}8NdpUq)lQtlii9nCO0HJg)g8IG;3?hku8p;7PM(?7doqa%-AlNNjgIs*) z_0T3(NU~AG0L(DT>PZda9RuNd{uL&kA#~0N9g=-Lgl0qyU=~jJe0Xf%UQdjn@^@vs z(|u_ekZ5XJxG(A-P>&7WqrPuhtYzkmZDCycW8J>s7#>jm(sL(smTeeGhig;O6Tdm?RC}r>Q5zZa?m)n{lYPf9UWnfaGT~<|%*-pbU%wjR1xTbE zqS{O~lh4q16I7d+9R~G38N%2hV2~dC`SIgN@4!GAE2Om&z$TaTCb018A$3MW^8;wh zqF-RppsKAsLJRBXizqTh-&|T+VoaBhFO}9Gxf$BThKk-(Lg<2$w+Uto@cm+8zuZ!H z&0bK)64DlE82TY?bS0)ElZ_T6`wH0 zr{(^w+H$kE-IYoo8)tBK?7M_TL5A-NF?|f z5H>k>1Upw`9jiLDzkQ{ z7t{G4hrDlqPeV@aD_-+Ivd-9?1zmwSP{9mk)v5lTkw`U}75zotjGf(tA=8|vY8j08 zEZ>)69Ct*u&2u>^ar9PP?*MSkGF)bB3z-q6N|Uya7Xge^mZ#g6yAUD`8a+~cN}t#-wTg+A>7CK1Ro&Mh@cw^1)*jNC*gQf? z<9k}DZ)LUm6(T4KP11ZAXrokHo=XUm>5|I+{Bav z?&Og#1n16m5t0^>ig$@_!ab$}CH42#OiR&T!q-nxj{vD(eF^0W)1=FebB#Wc$mGSp z!T>egIg)C3bMH3I1=+hr=5LvheFhOed>+3%DJC#yIw$QZHu9&R6S2S~*veUrYd#NL z_0)CbaTUjo!H>jYQB+oX#k{ojq@yaIvp=?_CesU5mjJaExFrn6^V`nb4t;MD82|7% z`M-$;JX1%zh8vIrIJI^RJPvA5hxZYf=<81su%9j$bsUB7V1rlbjT-kH+wa%5y%%_e z%)tv>NebS^eIu^8z7y2Qr4hu8Yi(gWd+x?DA}GlhU~a?nXXz+ura7GXBFNfaSno~P z=6ZlaWxF5QL~*6HOuF=-w>3LolTE*C7I|STOErlAxwkhxXka*qhL7Q$^Gcs`>1{Lw zyYT*T$$BWqfnvE<<)r`pC|=@7)H=jp(4e+1VI?WvQz2a!IT4YC$tF z?M@I>NRJ#8XWopQoK<_+PwS8hybmFt%`5o$)N30X7weFpqG8qiKKrHCfr^3$YonMd zeAg_ZU~Svw+nkuBZ2U)*nj?x6=U05n^I85r_T&-&+=WvTCZa)8gtirt_oL(QRTW|R zAD(NEXY_2Co{kD;=Bx4=a%vu$*5ke|cd3VyD&RE3@fVMp?#@o-gB`^k@D&>IXQpg7 z4kVQRe4{(j8)(LkXcD##nz5fUl5E;&9Q&+VY(5_lOx0`@xq%qpG@*ki1Tq85hzh~Z z0xqq#JaleaBIVdv;Q~QCiT4MbER?XbxldhMk@t{E<)r4NrpQ% zhL%xkHS}GEstQC>Y|su(T$g(-mbGnb`Y`>*ai7p6jVnF~V2@yFNcb#__*GRL)SDJ= zX_mz;4slf^tprUd3_%ZSzov>UQtb%jg=>P(eJoM=KJp~fcMq&2V501 z*f{oUey>}CV|~r(aNAbyM`fzly3}r#ScV-+soPI?-n+6#^A?x|xe>+p4QK2Bp(=e@ zww`FM@ON+*{J48`U03917Tz1q@Tx*oikHc+_mee%hx^Fg#}U-tDHh*7xJj%1Ad-69 z1_p-GK@8u%g1|V~P+6V^Ogy}diBW$IgG@;Em#3Xx_9h1^;U3-!> zQf*y>hL~;C9HtPTOrk^B$X}gX!8`5vI-UBP2elaQv_FLk`gTf5KMHB4(v0R#e!tS>Fx0GF^9J#5=F&CUQ^45BE!WcD;XJ~0@Sp-qZ z9yn87&&ndmd9#M3XuNxQVIpt|bc)V?9n-nr(YXL~uhU)+Zijr535s6rtXFL;ugRvS zpw>skjbp~yC|xe@db4R!0Cd2XJJ&DU!pqj&MX1HVl6HnR>AI}%?*gWYga4~nSTC0G z2nbxU>Y=;#1y$dA{C4o$y;5+ssZn|3F9X55&(a6Xt!yoN&=I}Z_LA#b4^mXCcT+Hs zioYUmnw~%2+6EfNJ;2`uj3g{6at*2vju$>b!kF-@F3twXy4Z1_q&;xRSbP59*s_Js zcw*&m&wENIy@_W=N%7GXqz1G_i*=4Q&3x;&TmXIfAv~!Lk$wTB53_M-NON|1d3d<7 zQ4*QV`QMn3;BAooL-w^CH=7Lz;sJud$U+H>%O(K=r9r^n{YK7Z{A3hHVQS?S6xjKV zpF#toK}Uc+rLTlQ<1VD+v(m7G6_Nr2_2vfPF25!SNzUeSiAnR(SYXmGQqHE8sDJsK1r;d9D*=q*a5X9mSTStH=6u#^ltv} zK_J(1t}B9cmxVtoBO58d(6)jx$a(;E51&7O-tT+9lQaerK^Gvsb{KgO_}$u?IR_~K zQUQy<-?HTs(o5e~`n{2)XGT!7?C@{|XHG%EqgQZ`E#SEc;(-1pVam?sFKm^5GNz>e zSw!(1uXbm@8QCRvA+iV#!#VoJs6IFjadj|wa1(3>&$ImEFq9WMaYYA>VdiMjYfK0>1 zE45*}yMJZX^C9W77%7}-loS)*f0q_+@C7kM-X8$>gIx4Z3ZQ&5gb<#kPz}LIc%p^E zKhse+5hmK>defpK1bCwVB0LtrE8hlnBT8V1#M;Th0eA1)K z=H2ahNzO?DL)Z&^i$1tFRXy6bA1&VspNJwb?91%yTZ^G-rduAf#Qn*rib3>-L1mcmXnfgsjsi=oi_LBRN*3d+cCZYXg~Mp%BU$Wf8IstnlXD zKbf(vi+Bjw`8nqwbtwEB5JXk=88|;LmUZy^Dkq?a-S}p#Cl%=^Tx`GDGZHOVxh-^} zmjtmhgXbGZk<7CilxH`=FmX?r7;HY9Fo65<5uy)G#$57&_*6owDp%q==3l(YMcv*Zjn0(u8j{e69)@mT&=@XK5B;woK=G21gniBP#?iMx=>aU4sDt{5zGAN)laUk2g zSRHfM_|P|jwHZI;hh{qHO1kfT4UWuU+`8ty<-P0HnmHkfT+(T5>z2Gcr^}f8mHq8j5)dLfiJEG@jQD(=( zlGcPF0S150hrA!D+*!RMxLLB@(Bv7XFhZt^)vjThVUwq{{AlIx@d?iCrTV^JOcI&D zNlV=4o-Xx=82`8W)f%^G5+tXJX!HIk~YS==Ep4p%9g8IK3!Zr3`;dO*Juq31Kma0!Qq716ZMYoT^+x zE#`Cjw~WnI9itBIu}~nX!2pfu$MLS+FuPDcK3$4~7Z(+QNjtP4kI!8@Y9A~VRiNgn z(o=!~B(5{}TV#g8q+dn8)c-ZSZ|%zM7!VV{NPc*=eB0I3xo7O4Hl1^679TgwXm8tzq2odTTVaq#6v~H){LJbqrA&(AA`qeb^>Yr7LIw|DbV1Cx zXedvFI=}tbuU}l8oc4MxuzGg_AnK-21M?v?fCM376}vSAwNGVvWhEP)T)<*&ZT%3Y zdNu(8*D=w5?R_`;)y-^jWRSE5U;0tHQlBa&1qOv=MTDRD?fRF@7c5PCD}56jos3w| z^HP${747z>cs0JWUR%45mHR`DvR&}ouZ*q=Jte;zn9`&(ytosM>-9AeJDv97th7RL147TMi?^p6hS{PZ-BZjhY;chbim_K#5y1dRPbfL&9rC@ z@q?WtEGVeiM*c8Wc?nU5o8o8=;VB4eZ;-;swN249nX%URPehMpXHpO^>|YP~Dby(%r@? z4j$(C&5gT*RfB<;zi@xMaehoKW_tE*S7hv;1rj6|Mn?p&N+(GNe^dTU?*3cYNs>58@3KHTL#7UGq3h+gvl9vvO+hSo1F zBno)%6k;F7i9?I5Ji}+c@T93oaJD7#ojly!79Tx+EOhx2`V^E_n_j35l||kzE_@`4 zUY!s_Z|fTzjP(XjhsizZBGQzq!2QqBy3LBkI-0k&x2kB~>NeRWZ43&H!rVWDe{T<{ zOvDhU6GZc;v#_udkGAX35nZ;g`I6j&JyDsR?&y*xyivpQ`}a{+3)Laxif>#^&3z-_ zYij5(#jnFGZgOGaR)ESJct!r;Tu}`4_7(#^|Mmq+9KWu(LUdooJ~v?|TvH3!r(F|z zUrgaKE<~k`zuWFEHe>%dJH{^8&o5}>9_#P@`#R@uTUIz-*?RRs);F7$nzBmI1Dg?u z?&%%JWZu4Wr%#rK;j~O~C3Nx91H#wG^q8+{ab88@-J?Z)s`CVm4(Ao^tOPF31Hwym zB+BCO8BRqcx&+~+2fqS{2;nmcwr_s$8KJ{cVX7Q_`;9MaoNQbq**~v{q1MKe?G7cX zWinw+8@%yNvxem0|LW~Mz_ITCzVQ=9nGLej&P)g)qeMl7jO{UD!U@q!u9RPJ7Dqmfx@P~j(S%rx7#mw-Po;KULq7rfrUykqQ3! zdCt?B?U!K=tp(9FIW#<6Be9fZTjFxK?@zM1-r`RgT=6QPf%AC^q&U5uj%on#wlGP8)YPT1P)D?6^PBBSo{ z-0*zgGN;vCHHpWPM?_d$SH%S(Pl<%e=Z1BE1@DF|t7x%2k`K;O+RwzZGBsMJJ3q{5 z@awbzJ08nUO3E)!{rvnO$jf2p;3!UYHw1J!16n?gG!R?or|*LYq#kRV$Z7Hy#M$Wb z_xBCAEBgZb&P{B;g%Umr?ZFRf8X8G1dWHBkY0pi!-N6dIZQ7pKuMccPA(H;#!w1D@ zmCUe!m6eql^F}xDHy}afWpuP>1&k3kNLly+5%_y3;TFw6Q#>)YWMyO&{odRxcx`v? zt(7}N_oDCipA49cn=B_|+>^Rbs-S7Wbj#5WrZ8K?e!@-i4zLvfPla;!;pmkfvn2ihhouOT!oQF*>BuJGwUu{Bmi?m8Yk==Y;EUD9m>cEf%rml!qIm> zCIqDq3=IvLSeTnLBbCLSnSo(3?a-XP-NxCoxfc()aBl2+!R>bK8U^7_T+!={Y4yHO zYZT3N^lvoZ%#j@E@?5Yj(`DyeWh#DJFxxbFiHEGC>rQ0y@vK;nldBuMB}pOWg|-^S9!(0qwN?S%g4)Kme75G@OQ57`lo#ZVcAJHnY`g6A>GGbfeq4n4MTJ zAX4F@u&{7I5%MyqDF5zez;^qoQLF?Te+Lp}C{WGx^?-~)dYbDw6zul+@z0ZrP{7a< zXimJ*ZB3gcsu!~}Gubs&Rc&mL)AXsD`+%>9li?`Weh&X^0fM@)rm$l7z1dL_?!!M4 zRmufCc02dQ{Mo3`U3T1QSD@pPY}b&>G0UCjMX$Bbc4M=_GdiiLh}MIgg@xs#Rl%8oyCMNO{&T~I6qx|(pO5$&)0(n<$Nte;T@o;(H?sFS(bbiIplLFg)Bf%N@3q+|iG!F@3PI z_JHX1Onr7oZ7I&7c3J+!z3>jt2mGnQ?O}J14d!vr+r3E$uyLHYJ*75wp`OOf+`?Sf z)vgz9U?}rk9wTAhSvdE6tG0_T(75iKxX}Pq9kfKgh%K2H?z|!BmtPZONW{fgCu-|( z59pySvFgs6HYe%KwT+L4P(?*nR<;brZO6R){MiWf+5TN!T~D&IvaH~7i7dAJ1%rab zcZfHxLYXUts1-}3t974~l`V$nhqo24snXW4$?c*+^zonioRzh|c5J=|0=awgoojHW z*O=jk9e^$<5m2OSoEL!X6`EtO%<;jv4?t@l5EMy6xJhw2qbQHdbTsW~v62hVLLJFD zpNko1Y>X8&FFB;eQlf^N@%{t$OtIf_cx~@5!8Ti7Y+VTe905# z?N;!uOr|zZotRYSiz0K@hDL$oLQGQ#axEzfh1Fie2e*x!f}-Iz;)i-6SM^_V$7wuo zXJ_|3Au%yO%dF|WbWo&HLdNQT(PYkz*T?icr$jE#Frv$%#^M;D>7N2ns*oUw>ldD(*?1Z;pzRZP=x#7;_+eS*# zkNfj3YNp4{4m9{myT;qr+A2&MrMK3I=Xx8B7SSUbom=mM3R;A)=h0S)n{xp%++z(5kfW80r@+Tg$nH!>C|?->vuasH09N)f03u;X*U@!AnvtH*8}e5>6w z_?C3xvgh!E{l@$C_XX0-TQ()Nk?HlH1iNcgMg(5B<8+(i-{W(H)uT7$6Z(h3C!uci z=}w<79@>+wMK&KC5v&O1$cI`zZ)By{QQ!IWY1h7u6F)Exv@P9|W_dFptDZKp_ zOs!3J;=KdtP%Er^RQj?fLPD6rp{ejV_fCZgE{Lt0cxo%tYmU=h!T<%t@VWqZ)HFuQaJ+RLwG!iamqFf?N~6OeH_{ z_gI_G?uG&HB$5~!A+*CCd>ZHb{fsRHO^Tx4e7rQ(-cW_+TJOl7omtlXn+p>Q_(cT> zxFQ|{VmwyUMG@V=NGbymf`?EruAS5Ow*BGq@83^%`IbEZnW<`?ZI5-$%4bmU_o|YT z(gr?fE5me?I$K8x;5koOSXr&@mRJy>$V*R|OM2g{zcWPZhPm0NmD2qFfRE-$Bg*{( z!=ZFs2CP?(ynb4?;BbX2QAmSrSnJ?E-=oX>dlP4p3{eIDwOkkR;4ysrk(zi&@*DP_ z)Vrd1WvW}cxaMN*X*)yJwbg8_u4}ze(M@7kE#Q6%#rp|BDF5Dmc?g$ z-4qO6#c~e#5T8weF7)5vG>&e!3k!e!x?_cc33{=~m9@30Tc)PA3>))Y=TbQj5SgZT z$;p=5s;Vz+=6+s!l*+e_z(#vP0#=Z#IMRY)WPoExEwukYzw=mR4B=K(YO&kOoDX(d z9)9+TH&cOH&ic+gis7-A)q<^b%QQktMXL?l*R#*{-@D$(l<}qONhZGwjs4qaM(YV} z8+n7`giyyE{Wb1oKY6RY(k{a}d!Ka`7x_zBt|cXxUcPoLDY|*durG35GS_VL8O}X! zL@@PaW@OkwQxcUQ125X7)RWRbAJjgzpwk@NjM7wB?}3$Zu_Mb;*Xi1|4k5#b$RpnE z45)OS2rX>$LTBL$Ws2?MWUDuPqV@{nxG*fGaJd!^DH`H20C+h}auIn*!4CIbKnHPr z>Aa)0KS0X_F^i!gA*WM^LlE)v4M|M#+&ouJU*5aISVpci&MIoIF}|b!=}`4!g%rOR zG&~)`m8zV3p3xbv3nBM6;dFUn?~-=+ce;)UA(oGJEE9n)$3xivAW1cM;GA5qm{x$ z&&b%{)Y$me38pJn78adLNA{#;cpW)% zrmDp4wTc+F_|?_bZ~pBZ^geYa-6VupRT*fXz5u^eh;1hMSm2ekGBR&*Gwq__7we!4 z53O_JGYa$4@+RUlHgYFDbYwLuau7GfVx5R*g92C7(e*w>JobFJ=XnuiNaZ85;<*d{QTIBQN9qrkM7#hb?@FiL6iZjTytZ;xTZNYonw!iZftBY z6fHF*21XgFFGrL}|D%16$?v9JWV?Oyy=juRj(b4j_?YyZ=-Bl3mMuy5;N`2KA7QDL>V8iQ2(eHNDZL_yo4BcX;ttsdm( z>>5@c%tsou9Nlrw87pJb(7|UJrt5@7?FaP>3CEju0&-Y9`@e!m{5veb<<})U{M{i# z#nD&ex5)p2V8m9u7M$RlI{3*|`R#IY@2TtaZ|4(~=57+fo9!3tqmI-mtY^RY7bxRD z2S5JZ5Bu-nCjb1aiUE9Mo7_bA{i~=b4{1`O-a@C*x857p6?<$2cX z+ci4sk+FvlvmbtVn&!Tbzrg-%sd7U{{y~FYNsS7Zgw#xqnYLb8$<)nUDXQ1o&(!vc z_lk_PiOI=(XBII$`1Rm=<*Ab4wu(yb!skO_FSYis848%zv+c#WtAFdE{P*6cX!0CI(`ApxFFO-#9hVH_LPM`kE z$KtoNu-k$F?bkDRfIn|Q_Dt)Ei zcuOFU-iLFGue)}&bJrM`WqmhGRo!93M(TQ4qQL!bN-gQ0NkQs)iiW8L`xAYBgez}D zWVZ||&plsery>vjlc98E-(bLly&X=Yin$e=Z!SYkS?ufU+h6m%uA!j;#mecF@ymse znyD(Gx<*M#QYS{e>oPY!_l{l;zq zim{=01#HTHz0E!u+i$^XolwH>T+A)}Dm9qSgre?2YAoHjy33nk8hdII!kAU`1$)~% z+l}NyWo)b3WPK$T?#JIHy`x?`Fm>X?l#)8sE?9# zogOTGqA}eK`Ocmb`+Vg9#hG?zkByDJ;Sr5=x#~iKelj2*yrwRyM=J(n0Kw6yjcK$$w{foeaH9M!0zCl2{RHH;ZSLE$ka?q?f0arj@K;_w!zHNEiu4z~CB=21_~*v6h%b7^W#6yOG6DAfy#AfL$IWgp;qH8s((mnV z-~IG_-qjzx;(N}qe6xMsopLhthYC*f9b^Z>ke~JVw%Q`?e+)6);e~FI44?8!;nMVR z<%pbpyLXeo!lQP+JTP$AUh&9!#KU`Zq(G$sjQ9(F{Udhb8=;1NiLtR|HM zUDi?_iOlmnupwh(zWC~gNz-PGg!HAI!RUKEzvq)8B!?&lK@!YJ8S(izG~-9DfoF0ZLhU zd6d?rzgiy_NbjNec(dtcX=e5j&G>`dT(Nj}SG*_%0nPOV$w)ea8dCPqycpeDeDvgr zEx`;Ws%cyS0^#`f`20nw_W(kkMZ^({gF-6gnR<{f__MFhQoYP0f9gi*Du9AGpozll)aW7;99q~DWrLUX)qBB3JSq*M3FPKL7joXZF)~2d1EE z5(Z7^SzUkXUqOSl+FVsEfM!%N)1B#K6cgLG&~{fLGW;HBqFin9;X_f2QI|>lCG?*x0=3wh0*zimQj$1I{T8F_?Et<`$Hm{mjx3dAL+t+F zJKqIkO+vA6Wg}$+HwGw`?N#aXgkA^o;eFML_PbprC!p(pkH%$`;Dv+f-R)OgPjnh& zfDnaP7yK#LBlo_cuBGLe49r6vqA}ngr>;Y}mkv{y!4mw_cC&8Y5isEIVPa!DgZ&rl zfLd8Xe5rU5I!2i1Lbed}lpSjc#$kOpy+NuQ_4zMR*QGnzL^ia#vMYT2q}}hq&ve({ zTRg{c64cUjKR1f`!L;}1>%Y$gwFM6;Co9yG7G>;|zWkV>dykyP7F*xp+zY#-bx3*JL8bhjn8CW3R)e*YdU4TtP& zv1jKnk))dTr65F{ah}70PsdNvi2UzmRr$6)lfJi(0~RCR-+3qmwki+Zk;-P^*xKCL zwwb$s-yJI6oomt>7k;T-Rs10Yq;&tOGbN8+QelU!>J+yeCQtod^KCEBA?ZipW+y*1 zsJ8w7e4%{Lci)fpBx#>NkMrPK#haJxC~}8D-ZWRwDin+jEUcej91;Tl)lnNEHjnhy zZ%FO=If?+@pN^($=*Qa$URb%xT1H#GtG1*EUOxSN+_qn6nn(xhXi-`#@`sGGBy#p9 zI=8I-`N8JsLx`c&G$?IWJJtCNNq<}{G~QxDz85=GkhOJyUl4=kU2{rAZj*@ zJ~&;}NHAoVkKDjcr-sE$%I>!$G)#gFtL%fp1#OOdmXv)jUk&H zBwW5KU~!}J)OSX%@IcMxm1knT%!&(a09Hr|hWh=#0Z%**Jp7F*Rg6 z=`O>ZyZ7B%Uk#phXJ%3-e_tps{bT0l5VeFXZJ5sf;S?4_vQJhij}t%fyf2KdYiPcC zc5;P(iWgi1t#^^L6J;LsX|s5+9+f8P`p#zz zLW!Y-P)6ALvIhqR(PPTP8GB-(Ois(j1mo1N@SvcK84#~xcH;U!aO^((dYwsKU0tsO zMhJH8wUtzf5ZfJ5`}RBW-#Q3x*Cu}S#B+PU-6K+@VW*Ui7>GR-+0M7Ud9RvPWa*J& zx4+#BrT#v;FPvuuGseSqIMR5(@ZU}Rv*gKc{o+72&GRRo#OG4r0xi|)XW^h-8^{${ zVOaS)Umj}Zchp4_pZ-_Qm2gxk&P6Almtj546}hd zIAR%);e2x^k>TB!jbsmam8w zt+%t_ZA#Zn(Q~e;s2D52Y#0CE}^`GnZXNLL!`sQ_2+A$l?Ir@ zPu3%1)y|q3lN2F&HZ0i58R;C)aiQx%9dHSg6uisJXu-#&2WzA0?cEWKz`I=AnSYB@KBT%%uq$ofJvp_0HGlZrK{U-#uy4*2sDfTU& z<-eQ5tBvLh@nZ4R&dCjr`-?71huW(Bi7tu!d{g&kMmy)j)3o;sU$FN{ozDJ23UvEV z-qxw-bI%_@n?$${wa&WD#=~<$4r5H7!oxKsHweSSw%gv!q}D`d|>PR}?;faol>(B>&!)`G3*x)l|#H z2-_Qg(x7hFj%{@~o%&qy%!hEs)84hWXJ=$(U9*8X?LoZ>Un=*1ryU+2S3zqr7wY44 z$xG&dS&rkZ!99KbUT*{;ACmhyRh>}9<6i1sdgeAqy9j&kU&YN#*A;syha&l_rqv(7*4TKhbj+Jv9ipzILExe$u93V4K3!%;DnoymPk1$17r!dnLy@gF9YnhDn^eewRPaJ%9Fi~009}^ny6(+ z@Pa#%0rg!=Nn4x4UkVPllS_z?>rZ?dfkZh~kTSaA(YH2WSbwjDbF9_x1?G)KR3=XK&NLvaw7!ure8Xfn1!ti!6eSo$-9pRPMrbQZt50lFbWxP+Wy1TB&d*YFGmQ;Tax%6|cJePaDM<;cT;1Kw$dc#6-KygcJLfN0r6%!o+o2m4ua=>8L*SfAN<@ zy!-Xrw}sS$Qzdy0^ORPsSGbw~30z(IcK;CJ_h$#sL1%Nhi|D{n;+H?!T4RcTrd)hC ziB^`vsL)8ISI;lD*fSwxsHxY;4Z?wy&Ih(~>=pZ@c$3HoB3BI+xxQ{~hs5~Qk;8|L z=75|e5mTR+pdy@Kn(gPHCSWRuWj}h=DuA*n3H6_-6{7DWnfce(8vocPGX#I@wx_ux zr9l)(K2Kv?o5)0`-4$ZAAO$&jc_q>BFh*!Z-u)H+=MCYa{14@0CV;4Kf#CU=d!zL6 zCipBJ90@#qXrh$lZn?b}s=k@hzqK;^siVO;$CO?*Ra)Np)e)r= zsB;*?4RV*q3R?`{mnRK2eVuYFIPHY(|5PjvH@>&H`FU8ztSQqbX7U&%55uxtMt+4; z6Wy%gOX0RB! zZgp#kWadyM3L&K;9u9y5iC0h$L3ADKX+ccsb0SpM)wzqienFZtDFHPVu)WbB#=oH)7>PBFk*ctlMYf_}@7l=j5HH zd+1%ij`sU}!MKF)&;;~r+V9d(o$`zTxN-FH!;Lm^IBdFA0_U_oG zAgPf7=%Wd>-B%RUTHVneKfuzG6QK1v3l)kdwmzTi6?CpRNXmP9+)BWa^?@enO{h)! zf}JXvE#=^TI=k9h<9qy(k8&hjiF}E+f{ucQXH3%8Mx{lh3!PS~a*i5wQClimQDtic zujJiKFr_3g%?Q$eDl z$Q~2Sev1Cl#$Y3vWoP0~t7b(K#k?^s<|V{=JYW!LYR5V{8d>(vlc_O~Ir z9MiSF;Z2XlJ%<|2lD!-3T~76-*di4FN&5LqF99SiqY=9bp+pS657JYHBhqb|eA~8y zrmn8lp2gjAA(F0H-S9XtqD3D>D=rEpLc(zRPIY2(?N6Zw*9iRkP~mbPk07-5zCJ#G z@(|#rAeHmPl}>1d)8xjpdrD5^Yq+@fKGi0;jWL zNg+h5A1XMW>EYKSAC(|fv_o#V%AK=9;>;|1^j#|>?Yk>?%5d;-MDQzLHS>QXS+0Gw za}nQHqUn$%reDli%sG3d+>`C3?O2j6B~2$4L;##oY|qu+y1MB* z@I|mjD#sJetz9^XB{7i99O8^+hQh7?h-Yu;UFDA4iAg}LBu=AlkeVp&C5rG*GDK?Z zlXjI}O1Q-HxQX*rS6qLwf>O2Q;@F z5A`ceLx~L{E@lO3hMmpQbWo5`5>6Ntd~8g$M~Nv9U;3sx5Ex?D)(ueL@VxSC>}f#& zrqZArFAy4@BfN{8pn?_7W1%beMKsgMV`cU6po@-+PXFeLzWmMdgO3>XoHaxxZ?6f@ zw+l{0S5WxdZ}aShkncMw!yTIkp`9A(mF(Yd|( zduI9YZ5E5%AC9#b&HF1XhJC*8Nek(lx#aM`NxSg2fE;uibwE*aO-xM4uoUkh>@yHz)Cn3{M` zjfn={$E&AvK2htpa6bL|-|DFNq%$cA8hO{+Nc(i+dp@?mqwy z3jB?TLBgm_qgXgNJdM6T-EE2*=+Hl=up+B}3<1jaNZXX*Umcmaf3Cw;R}4q}Okqr|-j|cimnUC~7E_uCb?UGg=^C-~ zvDZ-u8w)Ga@hZ-`ShVK-mj(myFf(k!A9{YsrJdcoTCSwSApTACea@G6FD;C2l~Ov; z+@pW?a7dQ<$>v@~>s^wH(^OAWQcl#N-V0IT{ArWhLxDM8nl zBXM!@7A-y|aASHhX<{TLrKPg`Xg4n*wgDH#-I%N_&BosLK$As-o-x1ubRFLR;Idtg z9rrG8R8jvLILZd8zq4FH5xt`Cc2Oa%9dhUNQaNS9$8#m54ab{@7T$Rc1+1wwygPQx zr93RQbvb8FYU`l;6`!r=>e_y{rO8ML#?hP33{dI^Kx@a~U^&{KkX~Wrp0mGH&V1#qILqo7PeN4}m{_i8cRU5Z@Caf$aSM57JtztpicE-bg6iHZe8D z3Qfvgq~xbSQO+Mb87PGObUQ@wr05qaBebXx-bzW8J6&Td9V?#?xgWlB?ec3AeOt0E zbt^UP8`@1q#$)4`4K1X5lJlRq7!=le{DbVKeT)M-OgG$S!r<6UOZB?NdzCNubUxP( z-k9kd$vP_RcsEtq##29eF?rW5#%;23Bp}A+H7AVe+k@6rV4#Jla)p@U!Tb(r${eYTg5?Glzd~HZGSmH@kL; zST{;sEV#F$|HG`BbG?*i5k%<)HSH_M+~0hotaLp{CD7-{%cNfZL*&J^htibF*M~#- z4RfZSl=fAe9DB!U;qCokZvl-{6%SM4F%y-`&2QLaK1p6L`S<5y_E?@7QCT!@n4dau*KxuMo?PefVPf2}`{Co1IKwro7g z7|Lj*jyM7NYZP`hdj*nRxK#x3nyBk-y`!c?Ep-6es!{9(%ta>tkP_HJ}T5 z+}&DsvB+6IRt$=LBmKF@%4_i}R~~JzVMEQ%uzPPhdBOemRpoQqvdl~ReF3@w&jxQ# zKEO+#Y?EMN@MGw3bS|#7EY*`0XbD~4qxK1j9%97tg=Yw=SlEW(>K!qx=R3wyx3#y6 z!bEv*A^Y26Stfx%Yj)}US@nJoo(QDJ`JYMMB3ds7|2QqeT&?SJI!}SC&?_fD{{lpW zXYshp0ZB1z_3E)PGPds_O3C3OJn2YDXLX+KIrh0*M1|3=?B|`~$-^AvAEzDcsop)7bX4@R{@4rLv)^gGLiH ztnL=KdR7!~qz9z+37GB8ys_e=k+U*>3@L#z;R95EpR(re0bO@%->%pDsHn(`eL=@w zPce-Pyi-_L`Qq>zg3%{Ivov6c_@G;UN;tM5e>m1y3z3T=KcGdjlC3r=xA0G@eDq%K z$h1@t32`jCHi1Z#Pgql*5)!f{_ren2Z1o_{4G=`x;te5~xA@OrwfGqoB#ozGx}AMi zxpD}yub^nY(^^OP_NzUjqnaXk)wQ&%Im9hUOoaR{z2)||IKU=he1WPWZ_C|saD6(1 zHuc4Q7XwMX%aN^zOic}@Bz8hNcRFHCkuKg9C^bD8_%k2*U3JcU5S+OsL%MU}l)bT4 zzFDPP$Ykh1IMp+0nhsr*u%8J7XyQlM*Q8c{zIqQZ<2JeXyOEziKX6%!3JJxaKsKu+ zn&xtFMil_@Z|J~~N0l{8B*uuI02UxfpaEqJ^JIt{TpgT`wqz9Ew=iEsY4`6X`A02( zfR=?m^u0gF5TRsjehQOEy^&OHfMYAbfPThGSsS|YJ5ZmIfu*n}PNc)5dqi!ZB45~c2nUwY5oG|Z#LO-_!A4z`@TLx=nqe2o?5(hp3qyv%7(fxPuiy9dlkGTCA zl2gVsin9cw5cbwdCLMelZ!xh3^|*zl<+Ql*hTgL{k?cRj8Hr~IKSxKSg0oaVsXs;x zLM03Ti;G=^lDax2L$RIFfx%Z_6BR5_1TR2Xc!cYCr*CI?mq0&jZl&eTt(`>J(BfO@ z!>NS&g+ri?APTv)l({oHgH@0wn0X>rX=0fL^x3B4bcn)|bY}l6s-a8lCRgx(7Kqv% zB#O3{TG$hw#%0m&KNA8&a2JL*xC3kz8H3?{*;=}L+zf7sQaE~65bN~?V23D9muaFm z-k->GVxUz6M3)jIUKqmK4o{9Dq>h)+62+va&uiiI=#43ezMQ7+z-sM^Ojc$~_)_$) zUbVGHh}IS95WsYKymtZTD6BDy*L12vr*U6(KjJEaIc*C1TgiADzRi4&;%H zz_OxL&`QxB(ZF5x+Pyz1?5$efrj=}rN^sx@*XMT6cR^`oOk;dn_2c?1?OwNv8y{_V zeBsb@o>}P5_Z|g%1Y!V|;ZJH4oh_Xxv1ehFnZ~5i_6txBcRyzlu096XeG+%mGUOF0 zy!v?=pEv#jmum)6_ZYeZajmY`VPReBYHIfq;ifHzFtv>kC1E>f9W%#V357Q)(sN8v zd9*;mn%r#&g~AJ5lj4)g^_X)X5YuE zk6?KJVtLZR)F9?=?CSYA@RMUd=cx9}P@>+j%}2=d+ZzGa;MdxbPA)FDF^H{XG_&2nb*BG2Ea&qGJY9VS zQxI$wIi20zLWBbc58epED!iht-C0Lm3&)?7Y8zQw7YiIeJ~lM(`gd9F5(!3Ris)bx zL_9X%Dqz?(7Yu|JoMjrimm5GZyBv0^D#ktk#f#ng;D-?b5Sx{e5tKR^G41T+bpC1C z&98Xfj|;kvvAi^V!dLjDcNcmN7B%|27l=e%I*P*F<6bFjwNovEtH6Z#XJs)(Vm{3B7}~v zE^%zUuYjpMJAvg<%~r09LJK%}_jDH^>1c#qB*IC=fk)RhVgCRmliqe>%!kzc*&IwF z_(x@9Xy_@+eoq0JsOAr$uXx7byEpmB8KLSA7DgK( znV*F}f3453zWe2OP_4~cI^Dpux2^Fe1wptj(`ju$FX^&Qa!}8t2@rESNKm|?m}sJt zUT-Wm+QNA1p|{D&b^CT~pFXMSFh-Z<4Cg@mqZScK6uLb=t$IwXEb4rqE^ibjk}9>mj%-V>#-hY)%Eo2ZQJm z_H~y<(dY9%XG1JFIa%oS+?{A%-%&j88gMr8GXpBRPvS#D?#KV)K`?V%A1N| z;Yny;F_G5A4i3d(2nV8~xtGpCK?%}}mJo6|E)x$oGf4neAKC*r^Mf$lvDkx{d5VUE zLR&|NmYg6Jy@kQomey`=1>Z~#^j7U8z>_xBa5F6e`4Lq4dCKppEj(7%!>;kZeEy4d zWcMKJrX9QgWcg$qY!+k3OxW^LtKIYmcm73o&vq%=ja{Ysj}NvOpN4hn)1H14w|GsV zz_YYugC?WTEJjw4ajSCVg3$#6p`v6T8<}pX5z{Ggt^@o;vCSh4S#~9k)xLqsjt$3Hqbj4xprrus(Fwcr`C|H7D2T?pBvi7d^0z;VZe|5RFB z`6o&e=Ie!gFE8#915Hxs`zRI%ijs>m{RS$6P0cjnjlb-)HEi^y5?FOyd3J z;!S&kPnm;~Q)(=6l27cu=a)@ZXPk!@f-jym$Qnk$YfX z98@K<@c#G@qBS9Q7inc+Ym*20dxzrnr-)Ke$yK(HT_b(pR?LAvexTx`Y(e%fIS2f6 zYC?fsj5J4xU`=tM#P=J!o<1OmFESjFJU{EnL3>|Dn1Lam>D<1HI!z;z^JOeO4>tmH zBgBrfiX<0*6YotYk;x7V{X8@7-YT{}s!jO2*NDZMqspObtvTrEc|wZ$fW={`pms?M|2$A6KDn`x-&~ PPnYDB&!?Qb{^0)sT=$w@?V5)hD_b5tZqMv~+t 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 literal 21039 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 diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseAndroidTest.java b/uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseAndroidTest.java index ec6dcaa0e..de390ff7c 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseAndroidTest.java +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseAndroidTest.java @@ -31,6 +31,7 @@ import junit.framework.*; import org.isoron.androidbase.*; +import org.isoron.androidbase.activities.*; import org.isoron.androidbase.utils.*; import org.isoron.uhabits.core.models.*; import org.isoron.uhabits.core.preferences.*; @@ -67,12 +68,15 @@ public class BaseAndroidTest extends TestCase protected CountDownLatch latch; - protected AndroidTestComponent component; + protected HabitsApplicationTestComponent appComponent; protected ModelFactory modelFactory; + protected HabitsActivityTestComponent component; + private boolean isDone = false; + @Override @Before public void setUp() { @@ -86,21 +90,31 @@ public void setUp() setTheme(R.style.AppBaseTheme); setLocale("en", "US"); - component = DaggerAndroidTestComponent + latch = new CountDownLatch(1); + + appComponent = DaggerHabitsApplicationTestComponent .builder() .appContextModule(new AppContextModule(targetContext.getApplicationContext())) .build(); - HabitsApplication.setComponent(component); - prefs = component.getPreferences(); - habitList = component.getHabitList(); - taskRunner = component.getTaskRunner(); - logger = component.getHabitsLogger(); + HabitsApplication.setComponent(appComponent); + prefs = appComponent.getPreferences(); + habitList = appComponent.getHabitList(); + taskRunner = appComponent.getTaskRunner(); + logger = appComponent.getHabitsLogger(); + modelFactory = appComponent.getModelFactory(); + + prefs.reset(); - modelFactory = component.getModelFactory(); fixtures = new HabitFixtures(modelFactory, habitList); + fixtures.purgeHabits(appComponent.getHabitList()); + Habit habit = fixtures.createEmptyHabit(); - latch = new CountDownLatch(1); + component = DaggerHabitsActivityTestComponent + .builder() + .activityContextModule(new ActivityContextModule(targetContext)) + .habitsApplicationComponent(appComponent) + .build(); } protected void assertWidgetProviderIsInstalled(Class componentClass) @@ -118,7 +132,7 @@ protected void assertWidgetProviderIsInstalled(Class componentClass) protected void awaitLatch() throws InterruptedException { - assertTrue(latch.await(5, TimeUnit.SECONDS)); + assertTrue(latch.await(1, TimeUnit.SECONDS)); } protected void setLocale(@NonNull String language, @NonNull String country) @@ -195,4 +209,10 @@ protected void stopTracing() { Debug.stopMethodTracing(); } + + protected Long day(int offset) + { + return DateUtils.getStartOfToday() - + offset * DateUtils.millisecondsInOneDay; + } } diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseViewTest.java b/uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseViewTest.java index 79a09fe45..c6c97ca6b 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseViewTest.java +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseViewTest.java @@ -21,6 +21,7 @@ import android.graphics.*; import android.support.annotation.*; +import android.support.test.*; import android.view.*; import android.widget.*; @@ -31,14 +32,14 @@ import java.io.*; import java.util.*; -import static android.os.Build.VERSION.*; +import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION_CODES.KITKAT; import static android.os.Build.VERSION_CODES.LOLLIPOP; -import static android.view.View.MeasureSpec.*; +import static android.view.View.MeasureSpec.makeMeasureSpec; public class BaseViewTest extends BaseAndroidTest { - double similarityCutoff = 0.00075; + public double similarityCutoff = 0.00015; @Override public void setUp() @@ -49,6 +50,7 @@ public void setUp() protected void assertRenders(View view, String expectedImagePath) throws IOException { + InstrumentationRegistry.getInstrumentation().waitForIdleSync(); expectedImagePath = getVersionedPath(expectedImagePath); Bitmap actual = renderView(view); if(actual == null) throw new IllegalStateException("actual is null"); @@ -198,6 +200,7 @@ public Bitmap renderView(View view) Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); + view.invalidate(); view.draw(canvas); return bitmap; } diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitFixtures.java b/uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitFixtures.java index 4eeb5f6b9..f7a7cd9cf 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitFixtures.java +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitFixtures.java @@ -84,6 +84,9 @@ public Habit createLongNumericalHabit() habit.setName("Take a walk"); habit.setDescription("How many steps did you walk today?"); habit.setType(Habit.NUMBER_HABIT); + habit.setTargetType(Habit.AT_LEAST); + habit.setTargetValue(200.0); + habit.setUnit("steps"); habitList.add(habit); long timestamp = DateUtils.getStartOfToday(); diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitsActivityTestComponent.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitsActivityTestComponent.kt new file mode 100644 index 000000000..dde1b5a90 --- /dev/null +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitsActivityTestComponent.kt @@ -0,0 +1,53 @@ +/* + * 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 + +import dagger.* +import org.isoron.androidbase.activities.* +import org.isoron.uhabits.activities.* +import org.isoron.uhabits.activities.about.* +import org.isoron.uhabits.activities.habits.list.* +import org.isoron.uhabits.activities.habits.list.views.* +import org.isoron.uhabits.activities.habits.show.* +import org.isoron.uhabits.core.ui.screens.habits.list.* +import org.mockito.Mockito.* + +@Module +class TestModule { + @Provides fun ListHabitsBehavior() = mock(ListHabitsBehavior::class.java) +} + +@ActivityScope +@Component(modules = arrayOf( + ActivityContextModule::class, + AboutModule::class, + HabitsActivityModule::class, + ListHabitsModule::class, + ShowHabitModule::class, + HabitModule::class, + TestModule::class +), dependencies = arrayOf(HabitsApplicationComponent::class)) +interface HabitsActivityTestComponent { + fun getCheckmarkPanelViewFactory(): CheckmarkPanelViewFactory + fun getHabitCardViewFactory(): HabitCardViewFactory + fun getCheckmarkButtonViewFactory(): CheckmarkButtonViewFactory + fun getNumberButtonViewFactory(): NumberButtonViewFactory + fun getNumberPanelViewFactory(): NumberPanelViewFactory +} \ No newline at end of file diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/AndroidTestComponent.java b/uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitsApplicationTestComponent.java similarity index 90% rename from uhabits-android/src/androidTest/java/org/isoron/uhabits/AndroidTestComponent.java rename to uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitsApplicationTestComponent.java index ffd27be59..7ff4e2e26 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/AndroidTestComponent.java +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitsApplicationTestComponent.java @@ -19,7 +19,6 @@ package org.isoron.uhabits; - import org.isoron.androidbase.*; import org.isoron.uhabits.core.*; import org.isoron.uhabits.core.tasks.*; @@ -32,7 +31,8 @@ HabitsModule.class, SingleThreadModule.class, }) -public interface AndroidTestComponent extends HabitsApplicationComponent +public interface HabitsApplicationTestComponent + extends HabitsApplicationComponent { } @@ -42,7 +42,7 @@ class SingleThreadModule { @Provides @AppScope - public static TaskRunner provideTaskRunner() + static TaskRunner provideTaskRunner() { return new SingleThreadTaskRunner(); } diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/CommonSteps.java b/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/CommonSteps.java index b724467bf..fbbafe672 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/CommonSteps.java +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/CommonSteps.java @@ -142,7 +142,8 @@ public static void verifyShowsScreen(Screen screen) switch(screen) { case LIST_HABITS: - onView(withId(R.id.header)).check(matches(isDisplayed())); + onView(withClassName(endsWith("ListHabitsRootView"))) + .check(matches(isDisplayed())); break; case SHOW_HABIT: diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/ListHabitsSteps.java b/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/ListHabitsSteps.java index fbee024be..c8784138e 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/ListHabitsSteps.java +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/ListHabitsSteps.java @@ -20,7 +20,6 @@ package org.isoron.uhabits.acceptance.steps; import android.support.test.espresso.*; -import android.support.test.uiautomator.*; import android.view.*; import org.hamcrest.*; @@ -29,13 +28,18 @@ import java.util.*; -import static android.support.test.InstrumentationRegistry.*; -import static android.support.test.espresso.Espresso.*; -import static android.support.test.espresso.action.ViewActions.*; -import static android.support.test.espresso.matcher.ViewMatchers.*; +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant; +import static android.support.test.espresso.matcher.ViewMatchers.isEnabled; +import static android.support.test.espresso.matcher.ViewMatchers.withClassName; +import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withParent; +import static android.support.test.espresso.matcher.ViewMatchers.withText; import static org.hamcrest.CoreMatchers.*; import static org.isoron.uhabits.BaseUserInterfaceTest.device; -import static org.isoron.uhabits.acceptance.steps.CommonSteps.*; +import static org.isoron.uhabits.acceptance.steps.CommonSteps.clickText; public abstract class ListHabitsSteps { @@ -89,17 +93,8 @@ public static void clickMenu(MenuItem item) private static void clickTextInsideOverflowMenu(int id) { - UiObject toolbar = device.findObject( - new UiSelector().resourceId("org.isoron.uhabits:id/toolbar")); - if (toolbar.exists()) - { - onView(allOf(withContentDescription("More options"), - withParent(withParent(withId(R.id.toolbar))))).perform(click()); - } - else - { - openActionBarOverflowOrOptionsMenu(getTargetContext()); - } + onView(allOf(withContentDescription("More options"), withParent( + withParent(withClassName(endsWith("Toolbar")))))).perform(click()); onView(withText(id)).perform(click()); } diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonViewTest.java b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonViewTest.java deleted file mode 100644 index 53b2f1cc8..000000000 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonViewTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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.list.views; - -import android.support.test.runner.*; -import android.test.suitebuilder.annotation.*; - -import org.isoron.uhabits.*; -import org.isoron.uhabits.core.models.*; -import org.isoron.uhabits.utils.*; -import org.junit.*; -import org.junit.runner.*; - -import java.io.*; - -@RunWith(AndroidJUnit4.class) -@MediumTest -public class CheckmarkButtonViewTest extends BaseViewTest -{ - public static final String PATH = "habits/list/CheckmarkButtonView/"; - - private CheckmarkButtonView view; - - @Override - @Before - public void setUp() - { - super.setUp(); - view = new CheckmarkButtonView(targetContext); - view.setValue(Checkmark.UNCHECKED); - view.setColor(PaletteUtils.getAndroidTestColor(5)); - measureView(view, dpToPixels(48), dpToPixels(48)); - } - - @Test - public void testRender_explicitCheck() throws Exception - { - view.setValue(Checkmark.CHECKED_EXPLICITLY); - assertRendersCheckedExplicitly(); - } - - @Test - public void testRender_implicitCheck() throws Exception - { - view.setValue(Checkmark.CHECKED_IMPLICITLY); - assertRendersCheckedImplicitly(); - } - - @Test - public void testRender_unchecked() throws Exception - { - view.setValue(Checkmark.UNCHECKED); - assertRendersUnchecked(); - } - - protected void assertRendersCheckedExplicitly() throws IOException - { - assertRenders(view, PATH + "render_explicit_check.png"); - } - - protected void assertRendersCheckedImplicitly() throws IOException - { - assertRenders(view, PATH + "render_implicit_check.png"); - } - - protected void assertRendersUnchecked() throws IOException - { - assertRenders(view, PATH + "render_unchecked.png"); - } -} \ No newline at end of file diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonViewTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonViewTest.kt new file mode 100644 index 000000000..9c6e52533 --- /dev/null +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonViewTest.kt @@ -0,0 +1,99 @@ +/* + * 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.list.views + +import android.support.test.filters.* +import android.support.test.runner.* +import org.isoron.uhabits.* +import org.isoron.uhabits.core.models.* +import org.isoron.uhabits.utils.* +import org.junit.* +import org.junit.runner.* + +@RunWith(AndroidJUnit4::class) +@MediumTest +class CheckmarkButtonViewTest : BaseViewTest() { + + private val PATH = "habits/list/CheckmarkButtonView" + lateinit var view: CheckmarkButtonView + + var toggled = false + + @Before + override fun setUp() { + super.setUp() + view = component.getCheckmarkButtonViewFactory().create().apply { + value = Checkmark.UNCHECKED + color = PaletteUtils.getAndroidTestColor(5) + onToggle = { toggled = true } + } + measureView(view, dpToPixels(48), dpToPixels(48)) + } + + @Test + fun testRender_explicitCheck() { + view.value = Checkmark.CHECKED_EXPLICITLY + assertRendersCheckedExplicitly() + } + + @Test + fun testRender_implicitCheck() { + view.value = Checkmark.CHECKED_IMPLICITLY + assertRendersCheckedImplicitly() + } + + @Test + fun testRender_unchecked() { + view.value = Checkmark.UNCHECKED + assertRendersUnchecked() + } + + @Test + fun testClick_withShortToggleDisabled() { + prefs.isShortToggleEnabled = false + view.performClick() + assertFalse(toggled) + } + + @Test + fun testClick_withShortToggleEnabled() { + prefs.isShortToggleEnabled = true + view.performClick() + assertTrue(toggled) + } + + @Test + fun testLongClick() { + view.performLongClick() + assertTrue(toggled) + } + + private fun assertRendersCheckedExplicitly() { + assertRenders(view, "$PATH/render_explicit_check.png") + } + + private fun assertRendersCheckedImplicitly() { + assertRenders(view, "$PATH/render_implicit_check.png") + } + + private fun assertRendersUnchecked() { + assertRenders(view, "$PATH/render_unchecked.png") + } +} \ No newline at end of file diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelViewTest.java b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelViewTest.java deleted file mode 100644 index b73f71d97..000000000 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelViewTest.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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.list.views; - -import android.support.test.runner.AndroidJUnit4; -import android.test.suitebuilder.annotation.*; - -import org.isoron.uhabits.core.models.Checkmark; -import org.isoron.uhabits.core.models.Habit; -import org.isoron.uhabits.BaseViewTest; -import org.isoron.uhabits.utils.*; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.concurrent.CountDownLatch; - -@RunWith(AndroidJUnit4.class) -@MediumTest -public class CheckmarkPanelViewTest extends BaseViewTest -{ - public static final String PATH = "habits/list/CheckmarkPanelView/"; - - private CountDownLatch latch; - private CheckmarkPanelView view; - private int checkmarks[]; - - @Override - @Before - public void setUp() - { - super.setUp(); - prefs.setShouldReverseCheckmarks(false); - - Habit habit = fixtures.createEmptyHabit(); - - latch = new CountDownLatch(1); - checkmarks = new int[]{ - Checkmark.CHECKED_EXPLICITLY, Checkmark.UNCHECKED, - Checkmark.CHECKED_IMPLICITLY, Checkmark.CHECKED_EXPLICITLY}; - - view = new CheckmarkPanelView(targetContext); - view.setValues(checkmarks); - view.setButtonCount(4); - view.setColor(PaletteUtils.getAndroidTestColor(7)); - - measureView(view, dpToPixels(200), dpToPixels(200)); - } - -// protected void waitForLatch() throws InterruptedException -// { -// assertTrue("Latch timeout", latch.await(1, TimeUnit.SECONDS)); -// } - - @Test - public void testRender() throws Exception - { - assertRenders(view, PATH + "render.png"); - } - -// @Test -// public void testToggleCheckmark_withLeftToRight() throws Exception -// { -// setToggleListener(); -// view.getButton(1).performToggle(); -// waitForLatch(); -// } -// -// @Test -// public void testToggleCheckmark_withReverseCheckmarks() throws Exception -// { -// prefs.setShouldReverseCheckmarks(true); -// view.setCheckmarkValues(checkmarks); // refresh after preference change -// -// setToggleListener(); -// view.getButton(2).performToggle(); -// waitForLatch(); -// } -} \ No newline at end of file diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelViewTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelViewTest.kt new file mode 100644 index 000000000..835259f18 --- /dev/null +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelViewTest.kt @@ -0,0 +1,110 @@ +/* + * 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.list.views + +import android.support.test.filters.* +import android.support.test.runner.* +import org.hamcrest.CoreMatchers.* +import org.hamcrest.MatcherAssert.* +import org.isoron.uhabits.* +import org.isoron.uhabits.core.models.Checkmark.* +import org.isoron.uhabits.utils.* +import org.junit.* +import org.junit.runner.* + +@RunWith(AndroidJUnit4::class) +@MediumTest +class CheckmarkPanelViewTest : BaseViewTest() { + + private val PATH = "habits/list/CheckmarkPanelView" + private lateinit var view: CheckmarkPanelView + + @Before + override fun setUp() { + super.setUp() + prefs.isCheckmarkSequenceReversed = false + + val checkmarks = intArrayOf(CHECKED_EXPLICITLY, + CHECKED_EXPLICITLY, + CHECKED_IMPLICITLY, + UNCHECKED, + UNCHECKED, + UNCHECKED, + CHECKED_EXPLICITLY) + + view = component.getCheckmarkPanelViewFactory().create().apply { + values = checkmarks + buttonCount = 4 + color = PaletteUtils.getAndroidTestColor(7) + } + view.onAttachedToWindow() + measureView(view, dpToPixels(200), dpToPixels(200)) + } + + @After + public override fun tearDown() { +// view.onDetachedFromWindow() + super.tearDown() + } + + @Test + fun testRender() { + assertRenders(view, "$PATH/render.png") + } + + @Test + fun testRender_withDifferentColor() { + view.color = PaletteUtils.getAndroidTestColor(1) + assertRenders(view, "$PATH/render_different_color.png") + } + + @Test + fun testRender_Reversed() { + prefs.isCheckmarkSequenceReversed = true + assertRenders(view, "$PATH/render_reversed.png") + } + + @Test + fun testRender_withOffset() { + view.dataOffset = 3 + assertRenders(view, "$PATH/render_offset.png") + } + + @Test + fun testToggle() { + var timestamps = mutableListOf() + view.onToggle = { timestamps.add(it) } + view.buttons[0].performLongClick() + view.buttons[2].performLongClick() + view.buttons[3].performLongClick() + assertThat(timestamps, equalTo(listOf(day(0), day(2), day(3)))) + } + + @Test + fun testToggle_withOffset() { + var timestamps = LongArray(0) + view.dataOffset = 3 + view.onToggle = { timestamps += it } + view.buttons[0].performLongClick() + view.buttons[2].performLongClick() + view.buttons[3].performLongClick() + assertThat(timestamps, equalTo(longArrayOf(day(3), day(5), day(6)))) + } +} \ No newline at end of file diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/HabitCardViewTest.java b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/HabitCardViewTest.java deleted file mode 100644 index 6133f36d6..000000000 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/HabitCardViewTest.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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.list.views; - -import android.support.test.runner.*; -import android.test.suitebuilder.annotation.*; - -import org.isoron.uhabits.*; -import org.isoron.uhabits.core.models.*; -import org.isoron.uhabits.core.utils.*; -import org.junit.*; -import org.junit.runner.*; - -@RunWith(AndroidJUnit4.class) -@MediumTest -public class HabitCardViewTest extends BaseViewTest -{ - private HabitCardView view; - - public static final String PATH = "habits/list/HabitCardView/"; - - private Habit habit; - - @Override - public void setUp() - { - super.setUp(); - setTheme(R.style.AppBaseTheme); - - habit = fixtures.createLongHabit(); - CheckmarkList checkmarks = habit.getCheckmarks(); - - long today = DateUtils.getStartOfToday(); - long day = DateUtils.millisecondsInOneDay; - int[] values = checkmarks.getValues(today - 5 * day, today); - - view = new HabitCardView(targetContext); - view.setHabit(habit); - view.setValues(values); - view.setSelected(false); - view.setScore(habit.getScores().getTodayValue()); - view.setButtonCount(6); - measureView(view, dpToPixels(400), dpToPixels(50)); - } - - @Test - public void testRender() throws Exception - { - assertRenders(view, PATH + "render.png"); - } - - @Test - public void testRender_selected() throws Exception - { - view.setSelected(true); - measureView(view, dpToPixels(400), dpToPixels(50)); - assertRenders(view, PATH + "render_selected.png"); - } - - @Test - public void testChangeModel() throws Exception - { - habit.setName("Wake up early"); - habit.setColor(2); - habit.getObservable().notifyListeners(); - Thread.sleep(500); - assertRenders(view, PATH + "render_changed.png"); - } -} diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/HabitCardViewTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/HabitCardViewTest.kt new file mode 100644 index 000000000..5660b862e --- /dev/null +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/HabitCardViewTest.kt @@ -0,0 +1,86 @@ +/* + * 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.list.views + +import android.support.test.filters.* +import android.support.test.runner.* +import org.isoron.uhabits.* +import org.isoron.uhabits.core.models.* +import org.junit.* +import org.junit.runner.* + +@RunWith(AndroidJUnit4::class) +@MediumTest +class HabitCardViewTest : BaseViewTest() { + + val PATH = "habits/list/HabitCardView" + lateinit private var view: HabitCardView + lateinit private var habit1: Habit + lateinit private var habit2: Habit + + override fun setUp() { + super.setUp() + setTheme(R.style.AppBaseTheme) + + habit1 = fixtures.createLongHabit() + habit2 = fixtures.createLongNumericalHabit() + view = component.getHabitCardViewFactory().create().apply { + habit = habit1 + values = habit1.checkmarks.allValues + score = habit1.scores.todayValue + isSelected = false + buttonCount = 5 + } + latch.countDown() + + latch.await() + measureView(view, dpToPixels(400), dpToPixels(50)) + } + + @Test + fun testRender() { + assertRenders(view, "$PATH/render.png") + } + + @Test + fun testRender_selected() { + view.isSelected = true + measureView(view, dpToPixels(400), dpToPixels(50)) + assertRenders(view, "$PATH/render_selected.png") + } + + @Test + fun testRender_numerical() { + view.apply { + habit = habit2 + values = habit2.checkmarks.allValues + } + assertRenders(view, "$PATH/render_numerical.png") + } + + @Test + fun testChangeModel() { + habit1.name = "Wake up early" + habit1.color = 2 + habit1.observable.notifyListeners() + Thread.sleep(500) + assertRenders(view, "$PATH/render_changed.png") + } +} diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/HeaderViewTest.java b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/HeaderViewTest.java index 70d4ee66e..4c347c2a5 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/HeaderViewTest.java +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/HeaderViewTest.java @@ -57,22 +57,22 @@ public void setUp() @Test public void testRender() throws Exception { - when(prefs.shouldReverseCheckmarks()).thenReturn(false); + when(prefs.isCheckmarkSequenceReversed()).thenReturn(false); assertRenders(view, PATH + "render.png"); - verify(prefs).shouldReverseCheckmarks(); + verify(prefs).isCheckmarkSequenceReversed(); verifyNoMoreInteractions(prefs); } @Test public void testRender_reverse() throws Exception { - when(prefs.shouldReverseCheckmarks()).thenReturn(true); + when(prefs.isCheckmarkSequenceReversed()).thenReturn(true); assertRenders(view, PATH + "render_reverse.png"); - verify(prefs).shouldReverseCheckmarks(); + verify(prefs).isCheckmarkSequenceReversed(); verifyNoMoreInteractions(prefs); } } \ No newline at end of file diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/HintViewTest.java b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/HintViewTest.java index 9f8e5525a..44f512568 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/HintViewTest.java +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/HintViewTest.java @@ -47,9 +47,8 @@ public void setUp() { super.setUp(); - view = new HintView(targetContext); list = mock(HintList.class); - view.setHints(list); + view = new HintView(targetContext, list); measureView(view, 400, 200); String text = diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.java b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.java deleted file mode 100644 index 09343c04c..000000000 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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.list.views; - -import android.support.test.filters.*; -import android.support.test.runner.*; - -import org.isoron.uhabits.*; -import org.isoron.uhabits.utils.*; -import org.junit.*; -import org.junit.runner.*; - -import static org.hamcrest.CoreMatchers.*; -import static org.hamcrest.MatcherAssert.*; - -@RunWith(AndroidJUnit4.class) -@MediumTest -public class NumberButtonViewTest extends BaseViewTest -{ - public static final String PATH = "habits/list/NumberButtonView/"; - - private NumberButtonView view; - - - @Override - @Before - public void setUp() - { - super.setUp(); - - view = new NumberButtonView(targetContext); - view.setUnit("steps"); - view.setThreshold(100.0); - view.setColor(PaletteUtils.getAndroidTestColor(8)); - - measureView(view, dpToPixels(48), dpToPixels(48)); - } - - @Test - public void testFormatValue() - { - assertThat(NumberButtonView.formatValue(0.1235), equalTo("0.12")); - assertThat(NumberButtonView.formatValue(0.1000), equalTo("0.1")); - assertThat(NumberButtonView.formatValue(5.0), equalTo("5")); - assertThat(NumberButtonView.formatValue(5.25), equalTo("5.25")); - assertThat(NumberButtonView.formatValue(12.3456), equalTo("12.3")); - assertThat(NumberButtonView.formatValue(123.123), equalTo("123")); - assertThat(NumberButtonView.formatValue(321.2), equalTo("321")); - assertThat(NumberButtonView.formatValue(4321.2), equalTo("4.3k")); - assertThat(NumberButtonView.formatValue(54321.2), equalTo("54.3k")); - assertThat(NumberButtonView.formatValue(654321.2), equalTo("654k")); - assertThat(NumberButtonView.formatValue(7654321.2), equalTo("7.7M")); - assertThat(NumberButtonView.formatValue(87654321.2), equalTo("87.7M")); - assertThat(NumberButtonView.formatValue(987654321.2), equalTo("988M")); - assertThat(NumberButtonView.formatValue(1987654321.2), equalTo("2.0G")); - } - - @Test - public void testRender_aboveThreshold() throws Exception - { - view.setValue(500); - assertRenders(view, PATH + "render_above.png"); - } - - @Test - public void testRender_belowThreshold() throws Exception - { - view.setValue(99); - assertRenders(view, PATH + "render_below.png"); - } - - @Test - public void testRender_zero() throws Exception - { - view.setValue(0); - assertRenders(view, PATH + "render_zero.png"); - } -} \ No newline at end of file diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt new file mode 100644 index 000000000..d64830e21 --- /dev/null +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt @@ -0,0 +1,106 @@ +/* + * 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.list.views + +import android.support.test.filters.* +import android.support.test.runner.* +import org.hamcrest.CoreMatchers.* +import org.hamcrest.MatcherAssert.* +import org.isoron.uhabits.* +import org.isoron.uhabits.utils.* +import org.junit.* +import org.junit.runner.* + +@RunWith(AndroidJUnit4::class) +@MediumTest +class NumberButtonViewTest : BaseViewTest() { + + private val PATH = "habits/list/NumberButtonView" + private lateinit var view: NumberButtonView + var edited = false + + @Before + override fun setUp() { + super.setUp() + view = component.getNumberButtonViewFactory().create().apply { + units = "steps" + threshold = 100.0 + color = PaletteUtils.getAndroidTestColor(8) + onEdit = { edited = true } + } + measureView(view, dpToPixels(48), dpToPixels(48)) + } + + @Test + fun testFormatValue() { + assertThat(0.1235.toShortString(), equalTo("0.12")) + assertThat(0.1000.toShortString(), equalTo("0.1")) + assertThat(5.0.toShortString(), equalTo("5")) + assertThat(5.25.toShortString(), equalTo("5.25")) + assertThat(12.3456.toShortString(), equalTo("12.3")) + assertThat(123.123.toShortString(), equalTo("123")) + assertThat(321.2.toShortString(), equalTo("321")) + assertThat(4321.2.toShortString(), equalTo("4.3k")) + assertThat(54321.2.toShortString(), equalTo("54.3k")) + assertThat(654321.2.toShortString(), equalTo("654k")) + assertThat(7654321.2.toShortString(), equalTo("7.7M")) + assertThat(87654321.2.toShortString(), equalTo("87.7M")) + assertThat(987654321.2.toShortString(), equalTo("988M")) + assertThat(1987654321.2.toShortString(), equalTo("2.0G")) + } + + @Test + fun testRender_aboveThreshold() { + view.value = 500.0 + assertRenders(view, "$PATH/render_above.png") + } + + @Test + fun testRender_belowThreshold() { + view.value = 99.0 + assertRenders(view, "$PATH/render_below.png") + } + + @Test + fun testRender_zero() { + view.value = 0.0 + assertRenders(view, "$PATH/render_zero.png") + } + + @Test + fun testClick_shortToggleDisabled() { + prefs.isShortToggleEnabled = false + view.performClick() + assertFalse(edited) + } + + @Test + fun testClick_shortToggleEnabled() { + prefs.isShortToggleEnabled = true + view.performClick() + assertTrue(edited) + } + + @Test + fun testLongClick() { + view.performLongClick() + assertTrue(edited) + } +} \ No newline at end of file diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelViewTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelViewTest.kt new file mode 100644 index 000000000..3e07e8d84 --- /dev/null +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelViewTest.kt @@ -0,0 +1,105 @@ +/* + * 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.list.views + +import android.support.test.filters.* +import android.support.test.runner.* +import org.hamcrest.CoreMatchers.* +import org.hamcrest.MatcherAssert.* +import org.isoron.uhabits.* +import org.isoron.uhabits.utils.* +import org.junit.* +import org.junit.runner.* + +@RunWith(AndroidJUnit4::class) +@MediumTest +class NumberPanelViewTest : BaseViewTest() { + + private val PATH = "habits/list/NumberPanelView" + private lateinit var view: NumberPanelView + + @Before + override fun setUp() { + super.setUp() + prefs.isCheckmarkSequenceReversed = false + + val checkmarks = doubleArrayOf(1400.0, 5300.0, 0.0, + 14600.0, 2500.0, 45000.0) + + view = component.getNumberPanelViewFactory().create().apply { + values = checkmarks + buttonCount = 4 + color = PaletteUtils.getAndroidTestColor(7) + units = "steps" + threshold = 5000.0 + } + view.onAttachedToWindow() + measureView(view, dpToPixels(200), dpToPixels(200)) + } + + @After + public override fun tearDown() { + view.onDetachedFromWindow() + } + + @Test + fun testRender() { + assertRenders(view, "$PATH/render.png") + } + + @Test + fun testRender_withDifferentColor() { + view.color = PaletteUtils.getAndroidTestColor(1) + assertRenders(view, "$PATH/render_different_color.png") + } + + @Test + fun testRender_Reversed() { + prefs.isCheckmarkSequenceReversed = true + assertRenders(view, "$PATH/render_reversed.png") + } + + @Test + fun testRender_withOffset() { + view.dataOffset = 3 + assertRenders(view, "$PATH/render_offset.png") + } + + @Test + fun testEdit() { + var timestamps = LongArray(0) + view.onEdit = { timestamps += it } + view.buttons[0].performLongClick() + view.buttons[2].performLongClick() + view.buttons[3].performLongClick() + assertThat(timestamps, equalTo(longArrayOf(day(0), day(2), day(3)))) + } + + @Test + fun testEdit_withOffset() { + var timestamps = LongArray(0) + view.dataOffset = 3 + view.onEdit = { timestamps += it } + view.buttons[0].performLongClick() + view.buttons[2].performLongClick() + view.buttons[3].performLongClick() + assertThat(timestamps, equalTo(longArrayOf(day(3), day(5), day(6)))) + } +} \ No newline at end of file diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/AndroidThemeSwitcher.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/AndroidThemeSwitcher.java deleted file mode 100644 index 62b04c9bd..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/AndroidThemeSwitcher.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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; - -import android.support.annotation.*; - -import org.isoron.androidbase.activities.*; -import org.isoron.uhabits.R; -import org.isoron.uhabits.core.preferences.*; -import org.isoron.uhabits.core.ui.*; - -import javax.inject.*; - -@ActivityScope -public class AndroidThemeSwitcher extends ThemeSwitcher -{ - @NonNull - private final BaseActivity activity; - - @Inject - public AndroidThemeSwitcher(@NonNull BaseActivity activity, - @NonNull Preferences preferences) - { - super(preferences); - this.activity = activity; - } - - @Override - public void applyDarkTheme() - { - activity.setTheme(R.style.AppBaseThemeDark); - } - - @Override - public void applyLightTheme() - { - activity.setTheme(R.style.AppBaseTheme); - } - - @Override - public void applyPureBlackTheme() - { - activity.setTheme(R.style.AppBaseThemeDark_PureBlack); - - } -} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/package-info.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/AndroidThemeSwitcher.kt similarity index 53% rename from uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/package-info.java rename to uhabits-android/src/main/java/org/isoron/uhabits/activities/AndroidThemeSwitcher.kt index f9fc65e4b..9c8c8f6b3 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/package-info.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/AndroidThemeSwitcher.kt @@ -17,8 +17,30 @@ * with this program. If not, see . */ -/** - * Provides custom views that are used primarily on {@link - * org.isoron.uhabits.activities.habits.show.ShowHabitActivity}. - */ -package org.isoron.uhabits.activities.habits.show.views; \ No newline at end of file +package org.isoron.uhabits.activities + +import org.isoron.androidbase.activities.* +import org.isoron.uhabits.* +import org.isoron.uhabits.core.preferences.* +import org.isoron.uhabits.core.ui.* +import javax.inject.* + +@ActivityScope +class AndroidThemeSwitcher +@Inject constructor( + private val activity: BaseActivity, + preferences: Preferences +) : ThemeSwitcher(preferences) { + + override fun applyDarkTheme() { + activity.setTheme(R.style.AppBaseThemeDark) + } + + override fun applyLightTheme() { + activity.setTheme(R.style.AppBaseTheme) + } + + override fun applyPureBlackTheme() { + activity.setTheme(R.style.AppBaseThemeDark_PureBlack) + } +} diff --git a/uhabits-core/src/main/java/org/isoron/uhabits/core/io/package-info.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitModule.kt similarity index 80% rename from uhabits-core/src/main/java/org/isoron/uhabits/core/io/package-info.java rename to uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitModule.kt index c7a4f0a20..c4d76d03c 100644 --- a/uhabits-core/src/main/java/org/isoron/uhabits/core/io/package-info.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitModule.kt @@ -17,7 +17,12 @@ * with this program. If not, see . */ -/** - * Provides classes that deal with importing from and exporting to files. - */ -package org.isoron.uhabits.core.io; \ No newline at end of file +package org.isoron.uhabits.activities + +import dagger.* +import org.isoron.uhabits.core.models.* + +@Module +class HabitModule(private val habit: Habit) { + @Provides fun getHabit() = habit +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsActivity.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsActivity.java deleted file mode 100644 index 3cb8a2e31..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsActivity.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2017 Á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; - -import android.content.*; -import android.net.*; -import android.os.*; -import android.support.annotation.*; - -import org.isoron.androidbase.activities.*; -import org.isoron.uhabits.*; -import org.isoron.uhabits.core.models.*; - -public abstract class HabitsActivity extends BaseActivity -{ - private HabitsActivityComponent component; - - private HabitsApplicationComponent appComponent; - - public HabitsActivityComponent getActivityComponent() - { - return component; - } - - public HabitsApplicationComponent getAppComponent() - { - return appComponent; - } - - @Override - protected void onCreate(Bundle savedInstanceState) - { - super.onCreate(savedInstanceState); - - appComponent = - ((HabitsApplication) getApplicationContext()).getComponent(); - - Habit habit = getHabitFromIntent(appComponent.getHabitList()); - - component = DaggerHabitsActivityComponent - .builder() - .activityModule(new ActivityModule(this)) - .habitModule(new HabitModule(habit)) - .habitsApplicationComponent(appComponent) - .build(); - - component.getThemeSwitcher().apply(); - } - - @Nullable - private Habit getHabitFromIntent(@NonNull HabitList habitList) - { - Uri data = getIntent().getData(); - if(data == null) return null; - - Habit habit = habitList.getById(ContentUris.parseId(data)); - if (habit == null) throw new RuntimeException("habit not found"); - - return habit; - } -} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsActivity.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsActivity.kt new file mode 100644 index 000000000..6b4365f04 --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsActivity.kt @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2017 Á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 + +import android.content.* +import android.os.* +import org.isoron.androidbase.activities.* +import org.isoron.uhabits.* +import org.isoron.uhabits.core.models.* + +abstract class HabitsActivity : BaseActivity() { + lateinit var component: HabitsActivityComponent + lateinit var appComponent: HabitsApplicationComponent + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + appComponent = (applicationContext as HabitsApplication).component + + val habit = getHabitFromIntent(appComponent.habitList) + ?: appComponent.modelFactory.buildHabit() + + component = DaggerHabitsActivityComponent + .builder() + .activityContextModule(ActivityContextModule(this)) + .baseActivityModule(BaseActivityModule(this)) + .habitModule(HabitModule(habit)) + .habitsApplicationComponent(appComponent) + .build() + + component.themeSwitcher.apply() + } + + private fun getHabitFromIntent(habitList: HabitList): Habit? { + val data = intent.data ?: return null + val habit = habitList.getById(ContentUris.parseId(data)) + ?: throw RuntimeException("habit not found") + return habit + } +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsActivityComponent.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsActivityComponent.java deleted file mode 100644 index 3a3bd38de..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsActivityComponent.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2017 Á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; - -import org.isoron.androidbase.activities.*; -import org.isoron.uhabits.*; -import org.isoron.uhabits.activities.about.*; -import org.isoron.uhabits.activities.common.dialogs.*; -import org.isoron.uhabits.activities.habits.list.*; -import org.isoron.uhabits.activities.habits.list.views.*; -import org.isoron.uhabits.activities.habits.show.*; -import org.isoron.uhabits.core.ui.*; -import org.isoron.uhabits.core.ui.screens.habits.list.*; - -import dagger.*; - -@ActivityScope -@Component(modules = { - ActivityModule.class, - AboutModule.class, - HabitsActivityModule.class, - ListHabitsModule.class, - ShowHabitModule.class, - HabitModule.class -}, dependencies = { HabitsApplicationComponent.class }) -public interface HabitsActivityComponent -{ - AboutRootView getAboutRootView(); - - AboutScreen getAboutScreen(); - - ColorPickerDialogFactory getColorPickerDialogFactory(); - - HabitCardListAdapter getHabitCardListAdapter(); - - ListHabitsBehavior getListHabitsBehavior(); - - ListHabitsController getListHabitsController(); - - ListHabitsMenu getListHabitsMenu(); - - ListHabitsRootView getListHabitsRootView(); - - ListHabitsScreen getListHabitsScreen(); - - ListHabitsSelectionMenu getListHabitsSelectionMenu(); - - ShowHabitScreen getShowHabitScreen(); - - ThemeSwitcher getThemeSwitcher(); -} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsActivityComponent.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsActivityComponent.kt new file mode 100644 index 000000000..ed6906b74 --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsActivityComponent.kt @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2017 Á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 + +import dagger.* +import org.isoron.androidbase.activities.* +import org.isoron.uhabits.* +import org.isoron.uhabits.activities.about.* +import org.isoron.uhabits.activities.common.dialogs.* +import org.isoron.uhabits.activities.habits.list.* +import org.isoron.uhabits.activities.habits.list.views.* +import org.isoron.uhabits.activities.habits.show.* +import org.isoron.uhabits.core.ui.* +import org.isoron.uhabits.core.ui.screens.habits.list.* + +@ActivityScope +@Component(modules = arrayOf( + ActivityContextModule::class, + BaseActivityModule::class, + AboutModule::class, + HabitsActivityModule::class, + ListHabitsModule::class, + ShowHabitModule::class, + HabitModule::class +), dependencies = arrayOf(HabitsApplicationComponent::class)) +interface HabitsActivityComponent { + val aboutRootView: AboutRootView + val aboutScreen: AboutScreen + val colorPickerDialogFactory: ColorPickerDialogFactory + val habitCardListAdapter: HabitCardListAdapter + val listHabitsBehavior: ListHabitsBehavior + val listHabitsMenu: ListHabitsMenu + val listHabitsRootView: ListHabitsRootView + val listHabitsScreen: ListHabitsScreen + val listHabitsSelectionMenu: ListHabitsSelectionMenu + val showHabitScreen: ShowHabitScreen + val themeSwitcher: ThemeSwitcher +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsActivityModule.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsActivityModule.kt similarity index 73% rename from uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsActivityModule.java rename to uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsActivityModule.kt index 8263190e2..77145afbc 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsActivityModule.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsActivityModule.kt @@ -17,17 +17,14 @@ * with this program. If not, see . */ -package org.isoron.uhabits.activities; +package org.isoron.uhabits.activities -import org.isoron.androidbase.activities.*; -import org.isoron.uhabits.core.ui.*; - -import dagger.*; +import dagger.* +import org.isoron.androidbase.activities.* +import org.isoron.uhabits.core.ui.* @Module -public abstract class HabitsActivityModule -{ - @Binds - @ActivityScope - abstract ThemeSwitcher getThemeSwitcher(AndroidThemeSwitcher t); +abstract class HabitsActivityModule { + @Binds @ActivityScope + internal abstract fun getThemeSwitcher(t: AndroidThemeSwitcher): ThemeSwitcher } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsDirFinder.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsDirFinder.java deleted file mode 100644 index 8940bda7d..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsDirFinder.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2017 Á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; - -import android.support.annotation.*; - -import org.isoron.androidbase.*; -import org.isoron.uhabits.core.ui.screens.habits.list.*; -import org.isoron.uhabits.core.ui.screens.habits.show.*; - -import java.io.*; - -import javax.inject.*; - -public class HabitsDirFinder - implements ShowHabitMenuBehavior.System, ListHabitsBehavior.DirFinder -{ - private AndroidDirFinder androidDirFinder; - - @Inject - public HabitsDirFinder(@NonNull AndroidDirFinder androidDirFinder) - { - this.androidDirFinder = androidDirFinder; - } - - @Override - public File getCSVOutputDir() - { - return androidDirFinder.getFilesDir("CSV"); - } -} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardViewHolder.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsDirFinder.kt similarity index 62% rename from uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardViewHolder.java rename to uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsDirFinder.kt index a9d35b01e..54bf67390 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardViewHolder.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsDirFinder.kt @@ -16,16 +16,20 @@ * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ +package org.isoron.uhabits.activities -package org.isoron.uhabits.activities.habits.list.views; +import org.isoron.androidbase.* +import org.isoron.uhabits.core.ui.screens.habits.list.* +import org.isoron.uhabits.core.ui.screens.habits.show.* +import java.io.* +import javax.inject.* -import android.support.v7.widget.*; -import android.view.*; +class HabitsDirFinder @Inject +constructor( + private val androidDirFinder: AndroidDirFinder +) : ShowHabitMenuBehavior.System, ListHabitsBehavior.DirFinder { -public class HabitCardViewHolder extends RecyclerView.ViewHolder -{ - public HabitCardViewHolder(View itemView) - { - super(itemView); + override fun getCSVOutputDir(): File { + return androidDirFinder.getFilesDir("CSV")!! } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/AboutActivity.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/AboutActivity.java index 408844c7b..fc098b3c9 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/AboutActivity.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/AboutActivity.java @@ -33,8 +33,8 @@ public class AboutActivity extends HabitsActivity protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - AboutScreen screen = getActivityComponent().getAboutScreen(); - screen.setRootView(getActivityComponent().getAboutRootView()); + AboutScreen screen = getComponent().getAboutScreen(); + screen.setRootView(getComponent().getAboutRootView()); setScreen(screen); } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/package-info.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/package-info.java deleted file mode 100644 index e519806ab..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 . - */ - -/** - * Provides activity that shows information about the app. - */ -package org.isoron.uhabits.activities.about; \ No newline at end of file diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt new file mode 100644 index 000000000..a14ae4dbe --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2017 Á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.common.dialogs + +import android.content.* +import android.support.v7.app.* +import android.text.* +import android.view.* +import android.view.inputmethod.* +import android.widget.* +import org.isoron.androidbase.activities.* +import org.isoron.androidbase.utils.* +import org.isoron.uhabits.* +import org.isoron.uhabits.core.ui.screens.habits.list.* +import javax.inject.* + +class NumberPickerFactory +@Inject constructor( + @ActivityContext private val context: Context +) { + fun create(value: Double, + unit: String, + callback: ListHabitsBehavior.NumberPickerCallback): AlertDialog { + + val inflater = LayoutInflater.from(context) + val view = inflater.inflate(R.layout.number_picker_dialog, null) + + val picker = view.findViewById(R.id.picker) as NumberPicker + val picker2 = view.findViewById(R.id.picker2) as NumberPicker + val tvUnit = view.findViewById(R.id.tvUnit) as TextView + + val intValue = Math.round(value * 100).toInt() + + picker.minValue = 0 + picker.maxValue = Integer.MAX_VALUE / 100 + picker.value = intValue / 100 + picker.wrapSelectorWheel = false + + picker2.minValue = 0 + picker2.maxValue = 19 + picker2.setFormatter { v -> String.format("%02d", 5 * v) } + picker2.value = intValue % 100 / 5 + refreshInitialValue(picker2) + + tvUnit.text = unit + + val dialog = AlertDialog.Builder(context) + .setView(view) + .setTitle(R.string.change_value) + .setPositiveButton(android.R.string.ok) { _, _ -> + picker.clearFocus() + val v = picker.value + 0.05 * picker2.value + callback.onNumberPicked(v) + } + .create() + + InterfaceUtils.setupEditorAction(picker) { _, actionId, _ -> + if (actionId == EditorInfo.IME_ACTION_DONE) + dialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick() + false + } + + return dialog + } + + private fun refreshInitialValue(picker: NumberPicker) { + // Workaround for Android bug: + // https://code.google.com/p/android/issues/detail?id=35482 + val f = NumberPicker::class.java.getDeclaredField("mInputText") + f.isAccessible = true + val inputText = f.get(picker) as EditText + inputText.filters = arrayOfNulls(0) + } +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/BarChart.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/BarChart.java index 3d053ef5a..a81dec50a 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/BarChart.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/BarChart.java @@ -361,7 +361,7 @@ private void drawValue(Canvas canvas, RectF rect, double value) if (value / 1000 >= target) activeColor = primaryColor; - String label = NumberButtonView.formatValue(value / 1000); + String label = NumberButtonViewKt.toShortString(value / 1000); Rect rText = new Rect(); pText.getTextBounds(label, 0, label.length(), rText); diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/RingView.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/RingView.java index ac3d72890..0a29ca599 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/RingView.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/RingView.java @@ -114,13 +114,18 @@ public RingView(Context ctx, AttributeSet attrs) public void setBackgroundColor(int backgroundColor) { this.backgroundColor = backgroundColor; - postInvalidate(); + invalidate(); } public void setColor(int color) { this.color = color; - postInvalidate(); + invalidate(); + } + + public int getColor() + { + return color; } public void setIsTransparencyEnabled(boolean isTransparencyEnabled) @@ -131,19 +136,19 @@ public void setIsTransparencyEnabled(boolean isTransparencyEnabled) public void setPercentage(float percentage) { this.percentage = percentage; - postInvalidate(); + invalidate(); } public void setPrecision(float precision) { this.precision = precision; - postInvalidate(); + invalidate(); } public void setText(String text) { this.text = text; - postInvalidate(); + invalidate(); } public void setTextSize(float textSize) @@ -154,7 +159,7 @@ public void setTextSize(float textSize) public void setThickness(float thickness) { this.thickness = thickness; - postInvalidate(); + invalidate(); } @Override @@ -254,4 +259,14 @@ private void reallocateCache() Bitmap.createBitmap(diameter, diameter, Bitmap.Config.ARGB_8888); cacheCanvas = new Canvas(drawingCache); } + + public float getPercentage() + { + return percentage; + } + + public float getPrecision() + { + return precision; + } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/ScrollableChart.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/ScrollableChart.java index c488cb17a..ae880c264 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/ScrollableChart.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/ScrollableChart.java @@ -177,7 +177,7 @@ public boolean onTouchEvent(MotionEvent event) return detector.onTouchEvent(event); } - public void setDirection(int direction) + public void setScrollDirection(int direction) { if (direction != 1 && direction != -1) throw new IllegalArgumentException(); diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/TaskProgressBar.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/TaskProgressBar.kt new file mode 100644 index 000000000..13a23fc07 --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/TaskProgressBar.kt @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2017 Á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.common.views + +import android.content.* +import android.widget.* +import org.isoron.androidbase.activities.* +import org.isoron.uhabits.core.tasks.* + +class TaskProgressBar( + context: Context, + private val runner: TaskRunner +) : ProgressBar( + context, + null, + android.R.attr.progressBarStyleHorizontal +), TaskRunner.Listener { + + init { + visibility = BaseRootView.GONE + isIndeterminate = true + } + + override fun onTaskStarted(task: Task?) = update() + override fun onTaskFinished(task: Task?) = update() + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + runner.addListener(this) + update() + } + + override fun onDetachedFromWindow() { + runner.removeListener(this) + super.onDetachedFromWindow() + } + + fun update() { + val callback = { + val activeTaskCount = runner.activeTaskCount + val newVisibility = when (activeTaskCount) { + 0 -> GONE + else -> VISIBLE + } + if (visibility != newVisibility) visibility = newVisibility + } + postDelayed(callback, 500) + } +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/package-info.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/package-info.java deleted file mode 100644 index 1d50f26f0..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 . - */ - -/** - * Provides views that are used across the app, such as RingView. - */ -package org.isoron.uhabits.activities.common.views; \ No newline at end of file diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitDialog.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitDialog.java index 5553ad816..55ea8e691 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitDialog.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitDialog.java @@ -93,7 +93,7 @@ public void onActivityCreated(Bundle savedInstanceState) HabitsActivity activity = (HabitsActivity) getActivity(); colorPickerDialogFactory = - activity.getActivityComponent().getColorPickerDialogFactory(); + activity.getComponent().getColorPickerDialogFactory(); } @Override diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/package-info.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/package-info.java deleted file mode 100644 index 3d6e4e626..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 . - */ - -/** - * Provides dialogs for editing habits and related classes. - */ -package org.isoron.uhabits.activities.habits.edit; \ No newline at end of file diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsActivity.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsActivity.java deleted file mode 100644 index e81fb13fe..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsActivity.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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.list; - -import android.os.*; - -import org.isoron.uhabits.activities.*; -import org.isoron.uhabits.activities.habits.list.views.*; -import org.isoron.uhabits.core.preferences.*; -import org.isoron.uhabits.core.ui.*; -import org.isoron.uhabits.core.utils.*; - -/** - * Activity that allows the user to see and modify the list of habits. - */ -public class ListHabitsActivity extends HabitsActivity -{ - private HabitCardListAdapter adapter; - - private ListHabitsRootView rootView; - - private ListHabitsScreen screen; - - private boolean pureBlack; - - private Preferences prefs; - - private MidnightTimer midnightTimer; - - @Override - protected void onCreate(Bundle savedInstanceState) - { - super.onCreate(savedInstanceState); - midnightTimer = getAppComponent().getMidnightTimer(); - HabitsActivityComponent component = getActivityComponent(); - - ListHabitsMenu menu = component.getListHabitsMenu(); - ListHabitsSelectionMenu selectionMenu = component.getListHabitsSelectionMenu(); - ListHabitsController controller = component.getListHabitsController(); - - adapter = component.getHabitCardListAdapter(); - rootView = component.getListHabitsRootView(); - screen = component.getListHabitsScreen(); - - prefs = getAppComponent().getPreferences(); - pureBlack = prefs.isPureBlackEnabled(); - - screen.setMenu(menu); - screen.setController(controller); - screen.setSelectionMenu(selectionMenu); - rootView.setController(controller, selectionMenu); - -// if(prefs.isSyncEnabled()) -// startService(new Intent(this, SyncService.class)); - - setScreen(screen); - controller.onStartup(); - } - - @Override - protected void onPause() - { - midnightTimer.onPause(); - screen.onDettached(); - adapter.cancelRefresh(); - super.onPause(); - } - - @Override - protected void onResume() - { - adapter.refresh(); - screen.onAttached(); - rootView.postInvalidate(); - midnightTimer.onResume(); - - if (prefs.getTheme() == ThemeSwitcher.THEME_DARK && - prefs.isPureBlackEnabled() != pureBlack) - { - restartWithFade(ListHabitsActivity.class); - } - - super.onResume(); - } -} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsActivity.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsActivity.kt new file mode 100644 index 000000000..a72b62d5b --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsActivity.kt @@ -0,0 +1,70 @@ +/* + * 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.list + +import android.os.* +import org.isoron.uhabits.activities.* +import org.isoron.uhabits.activities.habits.list.views.* +import org.isoron.uhabits.core.preferences.* +import org.isoron.uhabits.core.ui.ThemeSwitcher.* +import org.isoron.uhabits.core.utils.* + +class ListHabitsActivity : HabitsActivity() { + + var pureBlack: Boolean = false + lateinit var adapter: HabitCardListAdapter + lateinit var rootView: ListHabitsRootView + lateinit var screen: ListHabitsScreen + lateinit var prefs: Preferences + lateinit var midnightTimer: MidnightTimer + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + prefs = appComponent.preferences + pureBlack = prefs.isPureBlackEnabled + midnightTimer = appComponent.midnightTimer + rootView = component.listHabitsRootView + screen = component.listHabitsScreen + adapter = component.habitCardListAdapter + + setScreen(screen) + component.listHabitsBehavior.onStartup() + } + + override fun onPause() { + midnightTimer.onPause() + screen.onDettached() + adapter.cancelRefresh() + super.onPause() + } + + override fun onResume() { + adapter.refresh() + screen.onAttached() + rootView.postInvalidate() + midnightTimer.onResume() + + if (prefs.theme == THEME_DARK && prefs.isPureBlackEnabled != pureBlack) { + restartWithFade(ListHabitsActivity::class.java) + } + + super.onResume() + } +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsController.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsController.java deleted file mode 100644 index f5e8fb86f..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsController.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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.list; - -import android.support.annotation.*; - -import org.isoron.androidbase.activities.*; -import org.isoron.uhabits.R; -import org.isoron.uhabits.activities.habits.list.views.*; -import org.isoron.uhabits.core.models.*; -import org.isoron.uhabits.core.tasks.*; -import org.isoron.uhabits.core.ui.screens.habits.list.*; -import org.isoron.uhabits.tasks.*; - -import java.io.*; - -import javax.inject.*; - -@ActivityScope -public class ListHabitsController - implements HabitCardListController.HabitListener -{ - @NonNull - private final ListHabitsBehavior behavior; - - @NonNull - private final ListHabitsScreen screen; - - @NonNull - private final HabitCardListAdapter adapter; - - @NonNull - private final TaskRunner taskRunner; - - private ImportDataTaskFactory importTaskFactory; - - private ExportDBTaskFactory exportDBFactory; - - @Inject - public ListHabitsController(@NonNull ListHabitsBehavior behavior, - @NonNull HabitCardListAdapter adapter, - @NonNull ListHabitsScreen screen, - @NonNull TaskRunner taskRunner, - @NonNull ImportDataTaskFactory importTaskFactory, - @NonNull ExportDBTaskFactory exportDBFactory) - { - this.behavior = behavior; - this.adapter = adapter; - this.screen = screen; - this.taskRunner = taskRunner; - this.importTaskFactory = importTaskFactory; - this.exportDBFactory = exportDBFactory; - } - - public void onEdit(@NonNull Habit habit, long timestamp) - { - behavior.onEdit(habit, timestamp); - } - - public void onExportCSV() - { - behavior.onExportCSV(); - } - - public void onExportDB() - { - taskRunner.execute(exportDBFactory.create(filename -> - { - if (filename != null) screen.showSendFileScreen(filename); - else screen.showMessage(R.string.could_not_export); - })); - } - - @Override - public void onHabitClick(@NonNull Habit h) - { - behavior.onClickHabit(h); - } - - @Override - public void onHabitReorder(@NonNull Habit from, @NonNull Habit to) - { - behavior.onReorderHabit(from, to); - } - - public void onImportData(@NonNull File file, - @NonNull OnFinishedListener finishedListener) - { - taskRunner.execute(importTaskFactory.create(file, result -> - { - switch (result) - { - case ImportDataTask.SUCCESS: - adapter.refresh(); - screen.showMessage(R.string.habits_imported); - break; - - case ImportDataTask.NOT_RECOGNIZED: - screen.showMessage(R.string.file_not_recognized); - break; - - default: - screen.showMessage(R.string.could_not_import); - break; - } - - finishedListener.onFinish(); - })); - } - - public void onInvalidEdit() - { - screen.showMessage(R.string.long_press_to_edit); - } - - @Override - public void onInvalidToggle() - { - screen.showMessage(R.string.long_press_to_toggle); - } - - public void onRepairDB() - { - behavior.onRepairDB(); - } - - public void onSendBugReport() - { - behavior.onSendBugReport(); - } - - public void onStartup() - { - behavior.onStartup(); - } - - @Override - public void onToggle(@NonNull Habit habit, long timestamp) - { - behavior.onToggle(habit, timestamp); - } - - public interface OnFinishedListener - { - void onFinish(); - } -} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenu.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenu.java deleted file mode 100644 index 0c8335284..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenu.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * 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.list; - -import android.support.annotation.*; -import android.view.*; - -import org.isoron.androidbase.activities.*; -import org.isoron.uhabits.R; -import org.isoron.uhabits.core.preferences.*; -import org.isoron.uhabits.core.ui.*; -import org.isoron.uhabits.core.ui.screens.habits.list.*; - -import javax.inject.*; - -@ActivityScope -public class ListHabitsMenu extends BaseMenu -{ - - @NonNull - private final ListHabitsMenuBehavior behavior; - - private final Preferences preferences; - - private ThemeSwitcher themeSwitcher; - - @Inject - public ListHabitsMenu(@NonNull BaseActivity activity, - @NonNull Preferences preferences, - @NonNull ThemeSwitcher themeSwitcher, - @NonNull ListHabitsMenuBehavior behavior) - { - super(activity); - this.preferences = preferences; - this.themeSwitcher = themeSwitcher; - this.behavior = behavior; - } - - @Override - public void onCreate(@NonNull Menu menu) - { - MenuItem nightModeItem = menu.findItem(R.id.actionToggleNightMode); - MenuItem hideArchivedItem = menu.findItem(R.id.actionHideArchived); - MenuItem hideCompletedItem = menu.findItem(R.id.actionHideCompleted); - nightModeItem.setChecked(themeSwitcher.isNightMode()); - hideArchivedItem.setChecked(!preferences.getShowArchived()); - hideCompletedItem.setChecked(!preferences.getShowCompleted()); - } - - @Override - public boolean onItemSelected(@NonNull MenuItem item) - { - switch (item.getItemId()) - { - case R.id.actionToggleNightMode: - behavior.onToggleNightMode(); - return true; - - case R.id.actionAdd: - behavior.onCreateHabit(); - return true; - - case R.id.actionFAQ: - behavior.onViewFAQ(); - return true; - - case R.id.actionAbout: - behavior.onViewAbout(); - return true; - - case R.id.actionSettings: - behavior.onViewSettings(); - return true; - - case R.id.actionHideArchived: - behavior.onToggleShowArchived(); - invalidate(); - return true; - - case R.id.actionHideCompleted: - behavior.onToggleShowCompleted(); - invalidate(); - return true; - - case R.id.actionSortColor: - behavior.onSortByColor(); - return true; - - case R.id.actionSortManual: - behavior.onSortByManually(); - return true; - - case R.id.actionSortName: - behavior.onSortByName(); - return true; - - case R.id.actionSortScore: - behavior.onSortByScore(); - return true; - - default: - return false; - } - } - - @Override - protected int getMenuResourceId() - { - return R.menu.list_habits; - } - -} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenu.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenu.kt new file mode 100644 index 000000000..572ae0af1 --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenu.kt @@ -0,0 +1,111 @@ +/* + * 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.list + +import android.view.* +import org.isoron.androidbase.activities.* +import org.isoron.uhabits.* +import org.isoron.uhabits.core.preferences.* +import org.isoron.uhabits.core.ui.* +import org.isoron.uhabits.core.ui.screens.habits.list.* +import javax.inject.* + +@ActivityScope +class ListHabitsMenu @Inject constructor( + activity: BaseActivity, + private val preferences: Preferences, + private val themeSwitcher: ThemeSwitcher, + private val behavior: ListHabitsMenuBehavior +) : BaseMenu(activity) { + + override fun onCreate(menu: Menu) { + val nightModeItem = menu.findItem(R.id.actionToggleNightMode) + val hideArchivedItem = menu.findItem(R.id.actionHideArchived) + val hideCompletedItem = menu.findItem(R.id.actionHideCompleted) + nightModeItem.isChecked = themeSwitcher.isNightMode + hideArchivedItem.isChecked = !preferences.showArchived + hideCompletedItem.isChecked = !preferences.showCompleted + } + + override fun onItemSelected(item: MenuItem): Boolean { + when (item.itemId) { + R.id.actionToggleNightMode -> { + behavior.onToggleNightMode() + return true + } + + R.id.actionAdd -> { + behavior.onCreateHabit() + return true + } + + R.id.actionFAQ -> { + behavior.onViewFAQ() + return true + } + + R.id.actionAbout -> { + behavior.onViewAbout() + return true + } + + R.id.actionSettings -> { + behavior.onViewSettings() + return true + } + + R.id.actionHideArchived -> { + behavior.onToggleShowArchived() + invalidate() + return true + } + + R.id.actionHideCompleted -> { + behavior.onToggleShowCompleted() + invalidate() + return true + } + + R.id.actionSortColor -> { + behavior.onSortByColor() + return true + } + + R.id.actionSortManual -> { + behavior.onSortByManually() + return true + } + + R.id.actionSortName -> { + behavior.onSortByName() + return true + } + + R.id.actionSortScore -> { + behavior.onSortByScore() + return true + } + + else -> return false + } + } + + override fun getMenuResourceId() = R.menu.list_habits +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsModule.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsModule.java deleted file mode 100644 index 09e8d4775..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsModule.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2017 Á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.list; - -import android.content.*; -import android.support.annotation.*; - -import org.isoron.androidbase.*; -import org.isoron.uhabits.activities.*; -import org.isoron.uhabits.activities.habits.list.views.*; -import org.isoron.uhabits.core.ui.screens.habits.list.*; - -import javax.inject.*; - -import dagger.*; - -class BugReporterProxy extends AndroidBugReporter - implements ListHabitsBehavior.BugReporter -{ - @Inject - public BugReporterProxy(@AppContext @NonNull Context context) - { - super(context); - } -} - -@Module -public abstract class ListHabitsModule -{ - @Binds - abstract ListHabitsMenuBehavior.Adapter getAdapter(HabitCardListAdapter adapter); - - @Binds - abstract ListHabitsBehavior.BugReporter getBugReporter(BugReporterProxy proxy); - - @Binds - abstract ListHabitsMenuBehavior.Screen getMenuScreen(ListHabitsScreen screen); - - @Binds - abstract ListHabitsBehavior.Screen getScreen(ListHabitsScreen screen); - - @Binds - abstract ListHabitsSelectionMenuBehavior.Adapter getSelMenuAdapter( - HabitCardListAdapter adapter); - - @Binds - abstract ListHabitsSelectionMenuBehavior.Screen getSelMenuScreen( - ListHabitsScreen screen); - - @Binds - abstract ListHabitsBehavior.DirFinder getSystem(HabitsDirFinder system); -} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsModule.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsModule.kt new file mode 100644 index 000000000..55ffc22cf --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsModule.kt @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2017 Á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.list + +import android.content.* +import dagger.* +import org.isoron.androidbase.* +import org.isoron.uhabits.activities.* +import org.isoron.uhabits.activities.habits.list.views.* +import org.isoron.uhabits.core.ui.screens.habits.list.* +import javax.inject.* + +class BugReporterProxy +@Inject constructor( + @AppContext context: Context +) : AndroidBugReporter(context), ListHabitsBehavior.BugReporter + +@Module +abstract class ListHabitsModule { + + @Binds + abstract fun getAdapter(adapter: HabitCardListAdapter): ListHabitsMenuBehavior.Adapter + + @Binds + abstract fun getBugReporter(proxy: BugReporterProxy): ListHabitsBehavior.BugReporter + + @Binds + abstract fun getMenuScreen(screen: ListHabitsScreen): ListHabitsMenuBehavior.Screen + + @Binds + abstract fun getScreen(screen: ListHabitsScreen): ListHabitsBehavior.Screen + + @Binds + abstract fun getSelMenuAdapter(adapter: HabitCardListAdapter): ListHabitsSelectionMenuBehavior.Adapter + + @Binds + abstract fun getSelMenuScreen(screen: ListHabitsScreen): ListHabitsSelectionMenuBehavior.Screen + + @Binds + abstract fun getSystem(system: HabitsDirFinder): ListHabitsBehavior.DirFinder +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsRootView.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsRootView.java deleted file mode 100644 index 13d31d1d5..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsRootView.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * 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.list; - -import android.content.*; -import android.support.annotation.*; -import android.support.v7.widget.Toolbar; -import android.view.*; -import android.widget.*; - -import org.isoron.androidbase.activities.*; -import org.isoron.androidbase.utils.*; -import org.isoron.uhabits.R; -import org.isoron.uhabits.activities.common.views.*; -import org.isoron.uhabits.activities.habits.list.views.*; -import org.isoron.uhabits.core.models.*; -import org.isoron.uhabits.core.tasks.*; -import org.isoron.uhabits.core.ui.screens.habits.list.*; - -import javax.inject.*; - -import butterknife.*; - -import static org.isoron.androidbase.utils.InterfaceUtils.*; - -@ActivityScope -public class ListHabitsRootView extends BaseRootView - implements ModelObservable.Listener, TaskRunner.Listener -{ - public static final int MAX_CHECKMARK_COUNT = 60; - - @BindView(R.id.listView) - HabitCardListView listView; - - @BindView(R.id.llEmpty) - ViewGroup llEmpty; - - @BindView(R.id.tvStarEmpty) - TextView tvStarEmpty; - - @BindView(R.id.toolbar) - Toolbar toolbar; - - @BindView(R.id.progressBar) - ProgressBar progressBar; - - @BindView(R.id.hintView) - HintView hintView; - - @BindView(R.id.header) - HeaderView header; - - @NonNull - private final HabitCardListAdapter listAdapter; - - private final TaskRunner runner; - - @Inject - public ListHabitsRootView(@ActivityContext Context context, - @NonNull HintListFactory hintListFactory, - @NonNull HabitCardListAdapter listAdapter, - @NonNull TaskRunner runner) - { - super(context); - addView(inflate(getContext(), R.layout.list_habits, null)); - ButterKnife.bind(this); - - this.listAdapter = listAdapter; - listView.setAdapter(listAdapter); - listAdapter.setListView(listView); - - this.runner = runner; - progressBar.setIndeterminate(true); - tvStarEmpty.setTypeface(InterfaceUtils.getFontAwesome(getContext())); - - String hints[] = - getContext().getResources().getStringArray(R.array.hints); - HintList hintList = hintListFactory.create(hints); - hintView.setHints(hintList); - - initToolbar(); - } - - @NonNull - @Override - public Toolbar getToolbar() - { - return toolbar; - } - - @Override - public void onModelChange() - { - updateEmptyView(); - } - - @Override - public void onTaskFinished(Task task) - { - updateProgressBar(); - } - - @Override - public void onTaskStarted(Task task) - { - updateProgressBar(); - } - - public void setController(@NonNull ListHabitsController controller, - @NonNull ListHabitsSelectionMenu menu) - { - HabitCardListController listController = - new HabitCardListController(listAdapter); - - listController.setHabitListener(controller); - listController.setSelectionListener(menu); - listView.setController(listController); - menu.setListController(listController); - header.setScrollController(new ScrollableChart.ScrollController() - { - @Override - public void onDataOffsetChanged(int newDataOffset) - { - listView.setDataOffset(newDataOffset); - } - }); - } - - @Override - protected void onAttachedToWindow() - { - super.onAttachedToWindow(); - runner.addListener(this); - updateProgressBar(); - listAdapter.getObservable().addListener(this); - } - - @Override - protected void onDetachedFromWindow() - { - listAdapter.getObservable().removeListener(this); - runner.removeListener(this); - super.onDetachedFromWindow(); - } - - @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) - { - int count = getCheckmarkCount(); - header.setButtonCount(count); - header.setMaxDataOffset(Math.max(MAX_CHECKMARK_COUNT - count, 0)); - listView.setCheckmarkCount(count); - super.onSizeChanged(w, h, oldw, oldh); - } - - private int getCheckmarkCount() - { - float nameWidth = getDimension(getContext(), R.dimen.habitNameWidth); - float labelWidth = Math.max(getMeasuredWidth() / 3, nameWidth); - float buttonWidth = getDimension(getContext(), R.dimen.checkmarkWidth); - return Math.min(MAX_CHECKMARK_COUNT, Math.max(0, - (int) ((getMeasuredWidth() - labelWidth) / buttonWidth))); - } - - private void updateEmptyView() - { - llEmpty.setVisibility( - listAdapter.getItemCount() > 0 ? View.GONE : View.VISIBLE); - } - - private void updateProgressBar() - { - postDelayed(() -> - { - int activeTaskCount = runner.getActiveTaskCount(); - int newVisibility = activeTaskCount > 0 ? VISIBLE : GONE; - if (progressBar.getVisibility() != newVisibility) - progressBar.setVisibility(newVisibility); - }, 500); - } -} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsRootView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsRootView.kt new file mode 100644 index 000000000..25377db0c --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsRootView.kt @@ -0,0 +1,135 @@ +/* + * 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.list + +import android.content.* +import android.os.Build.VERSION.* +import android.os.Build.VERSION_CODES.* +import android.support.v7.widget.Toolbar +import android.view.ViewGroup.LayoutParams.* +import android.widget.* +import org.isoron.androidbase.activities.* +import org.isoron.uhabits.* +import org.isoron.uhabits.activities.common.views.* +import org.isoron.uhabits.activities.habits.list.views.* +import org.isoron.uhabits.core.models.* +import org.isoron.uhabits.core.preferences.* +import org.isoron.uhabits.core.tasks.* +import org.isoron.uhabits.core.ui.screens.habits.list.* +import org.isoron.uhabits.core.utils.* +import org.isoron.uhabits.utils.* +import java.lang.Math.* +import javax.inject.* + +const val MAX_CHECKMARK_COUNT = 60 + +@ActivityScope +class ListHabitsRootView @Inject constructor( + @ActivityContext context: Context, + hintListFactory: HintListFactory, + preferences: Preferences, + midnightTimer: MidnightTimer, + runner: TaskRunner, + private val listAdapter: HabitCardListAdapter, + habitCardListViewFactory: HabitCardListViewFactory +) : BaseRootView(context), ModelObservable.Listener { + + val listView: HabitCardListView = habitCardListViewFactory.create() + val llEmpty = EmptyListView(context) + val tbar = buildToolbar() + val progressBar = TaskProgressBar(context, runner) + val hintView: HintView + val header = HeaderView(context, preferences, midnightTimer) + + init { + val hints = resources.getStringArray(R.array.hints) + val hintList = hintListFactory.create(hints) + hintView = HintView(context, hintList) + + addView(RelativeLayout(context).apply { + background = sres.getDrawable(R.attr.windowBackgroundColor) + addAtTop(tbar) + addBelow(header, tbar) + addBelow(listView, header, height = MATCH_PARENT) + addBelow(llEmpty, header, height = MATCH_PARENT) + addBelow(progressBar, header) { + it.topMargin = dp(-6.0f).toInt() + } + addAtBottom(hintView) + if (SDK_INT < LOLLIPOP) { + addBelow(ShadowView(context), tbar) + addBelow(ShadowView(context), header) + } + }, MATCH_PARENT, MATCH_PARENT) + + listAdapter.setListView(listView) + initToolbar() + } + + override fun getToolbar(): Toolbar { + return tbar + } + + override fun onModelChange() { + updateEmptyView() + } + + private fun setupControllers() { + header.setScrollController(object : ScrollableChart.ScrollController { + override fun onDataOffsetChanged(newDataOffset: Int) { + listView.dataOffset = newDataOffset + } + }) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + setupControllers() + listAdapter.observable.addListener(this) + } + + override fun onDetachedFromWindow() { + listAdapter.observable.removeListener(this) + super.onDetachedFromWindow() + } + + override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { + val count = getCheckmarkCount() + header.buttonCount = count + header.setMaxDataOffset(max(MAX_CHECKMARK_COUNT - count, 0)) + listView.checkmarkCount = count + super.onSizeChanged(w, h, oldw, oldh) + } + + private fun getCheckmarkCount(): Int { + val nameWidth = dim(R.dimen.habitNameWidth) + val buttonWidth = dim(R.dimen.checkmarkWidth) + val labelWidth = max((measuredWidth / 3).toFloat(), nameWidth) + val buttonCount = ((measuredWidth - labelWidth) / buttonWidth).toInt() + return min(MAX_CHECKMARK_COUNT, max(0, buttonCount)) + } + + private fun updateEmptyView() { + llEmpty.visibility = when (listAdapter.itemCount) { + 0 -> VISIBLE + else -> GONE + } + } +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.java deleted file mode 100644 index 7882b9600..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.java +++ /dev/null @@ -1,441 +0,0 @@ -/* - * 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.list; - -import android.app.*; -import android.content.*; -import android.net.*; -import android.support.annotation.*; -import android.support.v7.app.AlertDialog; -import android.text.*; -import android.view.*; -import android.widget.*; - -import org.isoron.androidbase.activities.*; -import org.isoron.androidbase.utils.*; -import org.isoron.uhabits.*; -import org.isoron.uhabits.activities.common.dialogs.*; -import org.isoron.uhabits.activities.habits.edit.*; -import org.isoron.uhabits.core.commands.*; -import org.isoron.uhabits.core.models.*; -import org.isoron.uhabits.core.preferences.*; -import org.isoron.uhabits.core.ui.*; -import org.isoron.uhabits.core.ui.callbacks.*; -import org.isoron.uhabits.core.ui.screens.habits.list.*; -import org.isoron.uhabits.intents.*; - -import java.io.*; -import java.lang.reflect.*; -import java.util.*; - -import javax.inject.*; - -import static android.content.DialogInterface.BUTTON_POSITIVE; -import static android.view.inputmethod.EditorInfo.IME_ACTION_DONE; - -@ActivityScope -public class ListHabitsScreen extends BaseScreen - implements CommandRunner.Listener, ListHabitsBehavior.Screen, - ListHabitsMenuBehavior.Screen, - ListHabitsSelectionMenuBehavior.Screen -{ - public static final int REQUEST_OPEN_DOCUMENT = 6; - - public static final int REQUEST_SETTINGS = 7; - - public static final int RESULT_BUG_REPORT = 4; - - public static final int RESULT_EXPORT_CSV = 2; - - public static final int RESULT_EXPORT_DB = 3; - - public static final int RESULT_IMPORT_DATA = 1; - - public static final int RESULT_REPAIR_DB = 5; - - @Nullable - private ListHabitsController controller; - - @NonNull - private final IntentFactory intentFactory; - - @NonNull - private final CommandRunner commandRunner; - - @NonNull - private final ConfirmDeleteDialogFactory confirmDeleteDialogFactory; - - @NonNull - private final ColorPickerDialogFactory colorPickerFactory; - - @NonNull - private final EditHabitDialogFactory editHabitDialogFactory; - - @NonNull - private final ThemeSwitcher themeSwitcher; - - @NonNull - private Preferences prefs; - - @Inject - public ListHabitsScreen(@NonNull BaseActivity activity, - @NonNull CommandRunner commandRunner, - @NonNull ListHabitsRootView rootView, - @NonNull IntentFactory intentFactory, - @NonNull ThemeSwitcher themeSwitcher, - @NonNull ConfirmDeleteDialogFactory confirmDeleteDialogFactory, - @NonNull ColorPickerDialogFactory colorPickerFactory, - @NonNull EditHabitDialogFactory editHabitDialogFactory, - @NonNull Preferences prefs) - { - super(activity); - setRootView(rootView); - this.prefs = prefs; - this.colorPickerFactory = colorPickerFactory; - this.commandRunner = commandRunner; - this.confirmDeleteDialogFactory = confirmDeleteDialogFactory; - this.editHabitDialogFactory = editHabitDialogFactory; - this.intentFactory = intentFactory; - this.themeSwitcher = themeSwitcher; - } - - @StringRes - private Integer getExecuteString(@NonNull Command command) - { - if(command instanceof ArchiveHabitsCommand) - return R.string.toast_habit_archived; - - if(command instanceof ChangeHabitColorCommand) - return R.string.toast_habit_changed; - - if(command instanceof CreateHabitCommand) - return R.string.toast_habit_created; - - if(command instanceof DeleteHabitsCommand) - return R.string.toast_habit_deleted; - - if(command instanceof EditHabitCommand) - return R.string.toast_habit_changed; - - if(command instanceof UnarchiveHabitsCommand) - return R.string.toast_habit_unarchived; - - return null; - } - - public void onAttached() - { - commandRunner.addListener(this); - } - - @Override - public void onCommandExecuted(@NonNull Command command, - @Nullable Long refreshKey) - { - if (command.isRemote()) return; - showMessage(getExecuteString(command)); - } - - public void onDettached() - { - commandRunner.removeListener(this); - } - - @Override - public void onResult(int requestCode, int resultCode, Intent data) - { - if (requestCode == REQUEST_OPEN_DOCUMENT) - onOpenDocumentResult(resultCode, data); - - if (requestCode == REQUEST_SETTINGS) onSettingsResult(resultCode); - } - - public void setController(@Nullable ListHabitsController controller) - { - this.controller = controller; - } - - @Override - public void applyTheme() - { - themeSwitcher.apply(); - activity.restartWithFade(ListHabitsActivity.class); - } - - @Override - public void showAboutScreen() - { - Intent intent = intentFactory.startAboutActivity(activity); - activity.startActivity(intent); - } - - @Override - public void showColorPicker(int defaultColor, - @NonNull OnColorPickedCallback callback) { - ColorPickerDialog picker = colorPickerFactory.create(defaultColor); - picker.setListener(callback); - activity.showDialog(picker, "picker"); - } - - public void showCreateBooleanHabitScreen() - { - EditHabitDialog dialog; - dialog = editHabitDialogFactory.createBoolean(); - activity.showDialog(dialog, "editHabit"); - } - - @Override - public void showCreateHabitScreen() - { - if (!prefs.isNumericalHabitsFeatureEnabled()) - { - showCreateBooleanHabitScreen(); - return; - } - - Dialog dialog = new AlertDialog.Builder(activity) - .setTitle("Type of habit") - .setItems(R.array.habitTypes, (d, which) -> - { - if (which == 0) showCreateBooleanHabitScreen(); - else showCreateNumericalHabitScreen(); - }) - .create(); - - dialog.show(); - } - - @Override - public void showDeleteConfirmationScreen( - @NonNull OnConfirmedCallback callback) - { - activity.showDialog(confirmDeleteDialogFactory.create(callback)); - } - - @Override - public void showEditHabitsScreen(List habits) - { - EditHabitDialog dialog; - dialog = editHabitDialogFactory.edit(habits.get(0)); - activity.showDialog(dialog, "editNumericalHabit"); - } - - @Override - public void showFAQScreen() - { - Intent intent = intentFactory.viewFAQ(activity); - activity.startActivity(intent); - } - - @Override - public void showHabitScreen(@NonNull Habit habit) - { - Intent intent = intentFactory.startShowHabitActivity(activity, habit); - activity.startActivity(intent); - } - - public void showImportScreen() - { - Intent intent = intentFactory.openDocument(); - activity.startActivityForResult(intent, REQUEST_OPEN_DOCUMENT); - } - - @Override - public void showIntroScreen() - { - Intent intent = intentFactory.startIntroActivity(activity); - activity.startActivity(intent); - } - - @Override - public void showMessage(@NonNull ListHabitsBehavior.Message m) - { - switch (m) - { - case COULD_NOT_EXPORT: - showMessage(R.string.could_not_export); - break; - - case IMPORT_SUCCESSFUL: - showMessage(R.string.habits_imported); - break; - - case IMPORT_FAILED: - showMessage(R.string.could_not_import); - break; - - case DATABASE_REPAIRED: - showMessage(R.string.database_repaired); - break; - - case COULD_NOT_GENERATE_BUG_REPORT: - showMessage(R.string.bug_report_failed); - break; - - case FILE_NOT_RECOGNIZED: - showMessage(R.string.file_not_recognized); - break; - } - } - - @Override - public void showNumberPicker(double value, - @NonNull String unit, - @NonNull - ListHabitsBehavior.NumberPickerCallback callback) - { - LayoutInflater inflater = activity.getLayoutInflater(); - View view = inflater.inflate(R.layout.number_picker_dialog, null); - - final NumberPicker picker; - final NumberPicker picker2; - final TextView tvUnit; - - picker = (NumberPicker) view.findViewById(R.id.picker); - picker2 = (NumberPicker) view.findViewById(R.id.picker2); - tvUnit = (TextView) view.findViewById(R.id.tvUnit); - - int intValue = (int) Math.round(value * 100); - - picker.setMinValue(0); - picker.setMaxValue(Integer.MAX_VALUE / 100); - picker.setValue(intValue / 100); - picker.setWrapSelectorWheel(false); - - picker2.setMinValue(0); - picker2.setMaxValue(19); - picker2.setFormatter(v -> String.format("%02d", 5 * v)); - picker2.setValue((intValue % 100) / 5); - refreshInitialValue(picker2); - - tvUnit.setText(unit); - - AlertDialog dialog = new AlertDialog.Builder(activity) - .setView(view) - .setTitle(R.string.change_value) - .setPositiveButton(android.R.string.ok, (d, which) -> - { - picker.clearFocus(); - double v = picker.getValue() + 0.05 * picker2.getValue(); - callback.onNumberPicked(v); - }) - .create(); - - InterfaceUtils.setupEditorAction(picker, (v, actionId, event) -> - { - if (actionId == IME_ACTION_DONE) - dialog.getButton(BUTTON_POSITIVE).performClick(); - return false; - }); - - dialog.show(); - } - - @Override - public void showSendBugReportToDeveloperScreen(String log) - { - int to = R.string.bugReportTo; - int subject = R.string.bugReportSubject; - showSendEmailScreen(to, subject, log); - } - - @Override - public void showSettingsScreen() - { - Intent intent = intentFactory.startSettingsActivity(activity); - activity.startActivityForResult(intent, REQUEST_SETTINGS); - } - - private void onOpenDocumentResult(int resultCode, Intent data) - { - if (controller == null) return; - if (resultCode != Activity.RESULT_OK) return; - - try - { - Uri uri = data.getData(); - ContentResolver cr = activity.getContentResolver(); - InputStream is = cr.openInputStream(uri); - - File cacheDir = activity.getExternalCacheDir(); - File tempFile = File.createTempFile("import", "", cacheDir); - - FileUtils.copy(is, tempFile); - controller.onImportData(tempFile, () -> tempFile.delete()); - } - catch (IOException e) - { - showMessage(R.string.could_not_import); - e.printStackTrace(); - } - } - - private void onSettingsResult(int resultCode) - { - if (controller == null) return; - - switch (resultCode) - { - case RESULT_IMPORT_DATA: - showImportScreen(); - break; - - case RESULT_EXPORT_CSV: - controller.onExportCSV(); - break; - - case RESULT_EXPORT_DB: - controller.onExportDB(); - break; - - case RESULT_BUG_REPORT: - controller.onSendBugReport(); - break; - - case RESULT_REPAIR_DB: - controller.onRepairDB(); - break; - } - } - - private void refreshInitialValue(NumberPicker picker2) - { - // Workaround for a bug on Android: - // https://code.google.com/p/android/issues/detail?id=35482 - try - { - Field f = NumberPicker.class.getDeclaredField("mInputText"); - f.setAccessible(true); - EditText inputText = (EditText) f.get(picker2); - inputText.setFilters(new InputFilter[0]); - } - catch (Exception e) - { - throw new RuntimeException(e); - } - } - - private void showCreateNumericalHabitScreen() - { - EditHabitDialog dialog; - dialog = editHabitDialogFactory.createNumerical(); - activity.showDialog(dialog, "editHabit"); - } -} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt new file mode 100644 index 000000000..bda22a46e --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt @@ -0,0 +1,264 @@ +/* + * 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.list + +import android.app.* +import android.content.* +import android.support.annotation.* +import dagger.* +import org.isoron.androidbase.activities.* +import org.isoron.androidbase.utils.* +import org.isoron.uhabits.* +import org.isoron.uhabits.activities.common.dialogs.* +import org.isoron.uhabits.activities.habits.edit.* +import org.isoron.uhabits.activities.habits.list.views.* +import org.isoron.uhabits.core.commands.* +import org.isoron.uhabits.core.models.* +import org.isoron.uhabits.core.preferences.* +import org.isoron.uhabits.core.tasks.* +import org.isoron.uhabits.core.ui.* +import org.isoron.uhabits.core.ui.callbacks.* +import org.isoron.uhabits.core.ui.screens.habits.list.* +import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior.Message.* +import org.isoron.uhabits.intents.* +import org.isoron.uhabits.tasks.* +import java.io.* +import javax.inject.* + +const val RESULT_IMPORT_DATA = 1 +const val RESULT_EXPORT_CSV = 2 +const val RESULT_EXPORT_DB = 3 +const val RESULT_BUG_REPORT = 4 +const val RESULT_REPAIR_DB = 5 +const val REQUEST_OPEN_DOCUMENT = 6 +const val REQUEST_SETTINGS = 7 + +@ActivityScope +class ListHabitsScreen +@Inject constructor( + activity: BaseActivity, + rootView: ListHabitsRootView, + private val commandRunner: CommandRunner, + private val intentFactory: IntentFactory, + private val themeSwitcher: ThemeSwitcher, + private val preferences: Preferences, + private val adapter: HabitCardListAdapter, + private val taskRunner: TaskRunner, + private val exportDBFactory: ExportDBTaskFactory, + private val importTaskFactory: ImportDataTaskFactory, + private val confirmDeleteDialogFactory: ConfirmDeleteDialogFactory, + private val colorPickerFactory: ColorPickerDialogFactory, + private val editHabitDialogFactory: EditHabitDialogFactory, + private val numberPickerFactory: NumberPickerFactory, + private val behavior: Lazy, + private val menu: Lazy, + private val selectionMenu: Lazy +) : BaseScreen(activity), + CommandRunner.Listener, + ListHabitsBehavior.Screen, + ListHabitsMenuBehavior.Screen, + ListHabitsSelectionMenuBehavior.Screen { + + init { + setRootView(rootView) + } + + fun onAttached() { + setMenu(menu.get()) + setSelectionMenu(selectionMenu.get()) + commandRunner.addListener(this) + } + + fun onDettached() { + commandRunner.removeListener(this) + } + + override fun onCommandExecuted(command: Command, refreshKey: Long?) { + if (command.isRemote) return + showMessage(getExecuteString(command)) + } + + override fun onResult(requestCode: Int, resultCode: Int, data: Intent?) { + when (requestCode) { + REQUEST_OPEN_DOCUMENT -> onOpenDocumentResult(resultCode, data) + REQUEST_SETTINGS -> onSettingsResult(resultCode) + } + } + + private fun onOpenDocumentResult(resultCode: Int, data: Intent?) { + if (data == null) return + if (resultCode != Activity.RESULT_OK) return + try { + val inStream = activity.contentResolver.openInputStream(data.data) + val cacheDir = activity.externalCacheDir + val tempFile = File.createTempFile("import", "", cacheDir) + FileUtils.copy(inStream, tempFile) + onImportData(tempFile) { tempFile.delete() } + } catch (e: IOException) { + showMessage(R.string.could_not_import) + e.printStackTrace() + } + } + + private fun onSettingsResult(resultCode: Int) { + when (resultCode) { + RESULT_IMPORT_DATA -> showImportScreen() + RESULT_EXPORT_CSV -> behavior.get().onExportCSV() + RESULT_EXPORT_DB -> onExportDB() + RESULT_BUG_REPORT -> behavior.get().onSendBugReport() + RESULT_REPAIR_DB -> behavior.get().onRepairDB() + } + } + + override fun applyTheme() { + themeSwitcher.apply() + activity.restartWithFade(ListHabitsActivity::class.java) + } + + override fun showAboutScreen() { + val intent = intentFactory.startAboutActivity(activity) + activity.startActivity(intent) + } + + fun showCreateBooleanHabitScreen() { + val dialog = editHabitDialogFactory.createBoolean() + activity.showDialog(dialog, "editHabit") + } + + override fun showCreateHabitScreen() { + if (!preferences.isNumericalHabitsFeatureEnabled) { + showCreateBooleanHabitScreen() + return + } + + val dialog = AlertDialog.Builder(activity) + .setTitle("Type of habit") + .setItems(R.array.habitTypes) { _, which -> + if (which == 0) showCreateBooleanHabitScreen() + else showCreateNumericalHabitScreen() + } + .create() + + dialog.show() + } + + override fun showDeleteConfirmationScreen(callback: OnConfirmedCallback) { + activity.showDialog(confirmDeleteDialogFactory.create(callback)) + } + + override fun showEditHabitsScreen(habits: List) { + val dialog = editHabitDialogFactory.edit(habits[0]) + activity.showDialog(dialog, "editNumericalHabit") + } + + override fun showFAQScreen() { + val intent = intentFactory.viewFAQ(activity) + activity.startActivity(intent) + } + + override fun showHabitScreen(habit: Habit) { + val intent = intentFactory.startShowHabitActivity(activity, habit) + activity.startActivity(intent) + } + + fun showImportScreen() { + val intent = intentFactory.openDocument() + activity.startActivityForResult(intent, REQUEST_OPEN_DOCUMENT) + } + + override fun showIntroScreen() { + val intent = intentFactory.startIntroActivity(activity) + activity.startActivity(intent) + } + + override fun showMessage(m: ListHabitsBehavior.Message) { + showMessage(when (m) { + COULD_NOT_EXPORT -> R.string.could_not_export + IMPORT_SUCCESSFUL -> R.string.habits_imported + IMPORT_FAILED -> R.string.could_not_import + DATABASE_REPAIRED -> R.string.database_repaired + COULD_NOT_GENERATE_BUG_REPORT -> R.string.bug_report_failed + FILE_NOT_RECOGNIZED -> R.string.file_not_recognized + }) + } + + override fun showSendBugReportToDeveloperScreen(log: String) { + val to = R.string.bugReportTo + val subject = R.string.bugReportSubject + showSendEmailScreen(to, subject, log) + } + + override fun showSettingsScreen() { + val intent = intentFactory.startSettingsActivity(activity) + activity.startActivityForResult(intent, REQUEST_SETTINGS) + } + + override fun showColorPicker(defaultColor: Int, + callback: OnColorPickedCallback) { + val picker = colorPickerFactory.create(defaultColor) + picker.setListener(callback) + activity.showDialog(picker, "picker") + } + + override fun showNumberPicker(value: Double, + unit: String, + callback: ListHabitsBehavior.NumberPickerCallback) { + numberPickerFactory.create(value, unit, callback).show() + } + + @StringRes + private fun getExecuteString(command: Command): Int? { + when (command) { + is ArchiveHabitsCommand -> return R.string.toast_habit_archived + is ChangeHabitColorCommand -> return R.string.toast_habit_changed + is CreateHabitCommand -> return R.string.toast_habit_created + is DeleteHabitsCommand -> return R.string.toast_habit_deleted + is EditHabitCommand -> return R.string.toast_habit_changed + is UnarchiveHabitsCommand -> return R.string.toast_habit_unarchived + else -> return null + } + } + + private fun showCreateNumericalHabitScreen() { + val dialog = editHabitDialogFactory.createNumerical() + activity.showDialog(dialog, "editHabit") + } + + private fun onImportData(file: File, onFinished: () -> Unit) { + taskRunner.execute(importTaskFactory.create(file) { result -> + if (result == ImportDataTask.SUCCESS) { + adapter.refresh() + showMessage(R.string.habits_imported) + } else if (result == ImportDataTask.NOT_RECOGNIZED) { + showMessage(R.string.file_not_recognized) + } else { + showMessage(R.string.could_not_import) + } + onFinished() + }) + } + + private fun onExportDB() { + taskRunner.execute(exportDBFactory.create { filename -> + if (filename != null) showSendFileScreen(filename) + else showMessage(R.string.could_not_export) + }) + } +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsSelectionMenu.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsSelectionMenu.java deleted file mode 100644 index ac0a53a0f..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsSelectionMenu.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * 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.list; - -import android.support.annotation.*; -import android.view.*; - -import org.isoron.androidbase.activities.*; -import org.isoron.uhabits.R; -import org.isoron.uhabits.activities.habits.list.views.*; -import org.isoron.uhabits.core.commands.*; -import org.isoron.uhabits.core.ui.screens.habits.list.*; - -import javax.inject.*; - -@ActivityScope -public class ListHabitsSelectionMenu extends BaseSelectionMenu - implements HabitCardListController.SelectionListener -{ - @NonNull - private final ListHabitsScreen screen; - - @NonNull - CommandRunner commandRunner; - - private ListHabitsSelectionMenuBehavior behavior; - - @NonNull - private final HabitCardListAdapter listAdapter; - - @Nullable - private HabitCardListController listController; - - @Inject - public ListHabitsSelectionMenu(@NonNull ListHabitsScreen screen, - @NonNull HabitCardListAdapter listAdapter, - @NonNull CommandRunner commandRunner, - @NonNull ListHabitsSelectionMenuBehavior behavior) - { - this.screen = screen; - this.listAdapter = listAdapter; - this.commandRunner = commandRunner; - this.behavior = behavior; - } - - @Override - public void onFinish() - { - if (listController != null) listController.onSelectionFinished(); - super.onFinish(); - } - - @Override - public boolean onItemClicked(@NonNull MenuItem item) - { - switch (item.getItemId()) - { - case R.id.action_edit_habit: - behavior.onEditHabits(); - return true; - - case R.id.action_archive_habit: - behavior.onArchiveHabits(); - return true; - - case R.id.action_unarchive_habit: - behavior.onUnarchiveHabits(); - return true; - - case R.id.action_delete: - behavior.onDeleteHabits(); - return true; - - case R.id.action_color: - behavior.onChangeColor(); - return true; - - default: - return false; - } - } - - @Override - public boolean onPrepare(@NonNull Menu menu) - { - MenuItem itemEdit = menu.findItem(R.id.action_edit_habit); - MenuItem itemColor = menu.findItem(R.id.action_color); - MenuItem itemArchive = menu.findItem(R.id.action_archive_habit); - MenuItem itemUnarchive = menu.findItem(R.id.action_unarchive_habit); - - itemColor.setVisible(true); - itemEdit.setVisible(behavior.canEdit()); - itemArchive.setVisible(behavior.canArchive()); - itemUnarchive.setVisible(behavior.canUnarchive()); - setTitle(Integer.toString(listAdapter.getSelected().size())); - - return true; - } - - @Override - public void onSelectionChange() - { - invalidate(); - } - - @Override - public void onSelectionFinish() - { - finish(); - } - - @Override - public void onSelectionStart() - { - screen.startSelection(); - } - - public void setListController(HabitCardListController listController) - { - this.listController = listController; - } - - @Override - protected int getResourceId() - { - return R.menu.list_habits_selection; - } -} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsSelectionMenu.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsSelectionMenu.kt new file mode 100644 index 000000000..9493b651d --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsSelectionMenu.kt @@ -0,0 +1,95 @@ +/* + * 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.list + +import android.view.* +import dagger.* +import org.isoron.androidbase.activities.* +import org.isoron.uhabits.* +import org.isoron.uhabits.activities.habits.list.views.* +import org.isoron.uhabits.core.commands.* +import org.isoron.uhabits.core.ui.screens.habits.list.* +import javax.inject.* + +@ActivityScope +class ListHabitsSelectionMenu @Inject constructor( + private val screen: ListHabitsScreen, + private val listAdapter: HabitCardListAdapter, + var commandRunner: CommandRunner, + private val behavior: ListHabitsSelectionMenuBehavior, + private val listController: Lazy +) : BaseSelectionMenu() { + + override fun onFinish() { + listController.get().onSelectionFinished() + super.onFinish() + } + + override fun onItemClicked(item: MenuItem): Boolean { + when (item.itemId) { + R.id.action_edit_habit -> { + behavior.onEditHabits() + return true + } + + R.id.action_archive_habit -> { + behavior.onArchiveHabits() + return true + } + + R.id.action_unarchive_habit -> { + behavior.onUnarchiveHabits() + return true + } + + R.id.action_delete -> { + behavior.onDeleteHabits() + return true + } + + R.id.action_color -> { + behavior.onChangeColor() + return true + } + + else -> return false + } + } + + override fun onPrepare(menu: Menu): Boolean { + val itemEdit = menu.findItem(R.id.action_edit_habit) + val itemColor = menu.findItem(R.id.action_color) + val itemArchive = menu.findItem(R.id.action_archive_habit) + val itemUnarchive = menu.findItem(R.id.action_unarchive_habit) + + itemColor.isVisible = true + itemEdit.isVisible = behavior.canEdit() + itemArchive.isVisible = behavior.canArchive() + itemUnarchive.isVisible = behavior.canUnarchive() + setTitle(Integer.toString(listAdapter.selected.size)) + + return true + } + + fun onSelectionStart() = screen.startSelection() + fun onSelectionChange() = invalidate() + fun onSelectionFinish() = finish() + override fun getResourceId() = R.menu.list_habits_selection +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/package-info.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/package-info.java deleted file mode 100644 index 1a39e29de..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 . - */ - -/** - * Provides acitivity for listing habits and related classes. - */ -package org.isoron.uhabits.activities.habits.list; \ No newline at end of file diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/ButtonPanelView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/ButtonPanelView.kt new file mode 100644 index 000000000..bea2d4149 --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/ButtonPanelView.kt @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2017 Á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.list.views + +import android.content.* +import android.view.* +import android.view.View.MeasureSpec.* +import android.widget.* +import org.isoron.uhabits.* +import org.isoron.uhabits.core.preferences.* +import org.isoron.uhabits.utils.* + +abstract class ButtonPanelView( + context: Context, + val preferences: Preferences +) : LinearLayout(context), + Preferences.Listener { + + var buttonCount = 0 + set(value) { + field = value + inflateButtons() + } + + var dataOffset = 0 + set(value) { + field = value + setupButtons() + } + + var buttons = mutableListOf() + + override fun onCheckmarkSequenceChanged() { + inflateButtons() + } + + @Synchronized + protected fun inflateButtons() { + val reverse = preferences.isCheckmarkSequenceReversed + + buttons.clear() + repeat(buttonCount) { buttons.add(createButton()) } + + removeAllViews() + if (reverse) buttons.reversed().forEach { addView(it) } + else buttons.forEach { addView(it) } + setupButtons() + requestLayout() + } + + public override fun onAttachedToWindow() { + super.onAttachedToWindow() + preferences.addListener(this) + } + + public override fun onDetachedFromWindow() { + preferences.removeListener(this) + super.onDetachedFromWindow() + } + + override fun onMeasure(widthSpec: Int, heightSpec: Int) { + val buttonWidth = dim(R.dimen.checkmarkWidth) + val buttonHeight = dim(R.dimen.checkmarkHeight) + val width = (buttonWidth * buttonCount) + super.onMeasure(width.toMeasureSpec(EXACTLY), + buttonHeight.toMeasureSpec(EXACTLY)) + } + + protected abstract fun setupButtons() + protected abstract fun createButton(): T +} \ No newline at end of file diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.java deleted file mode 100644 index 9696f805b..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * 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.list.views; - -import android.content.*; -import android.content.res.*; -import android.graphics.*; -import android.support.annotation.*; -import android.text.*; -import android.util.*; -import android.view.*; - -import org.isoron.androidbase.utils.*; -import org.isoron.uhabits.*; -import org.isoron.uhabits.activities.*; -import org.isoron.uhabits.core.preferences.*; -import org.isoron.uhabits.utils.*; - -import static android.view.View.MeasureSpec.EXACTLY; -import static android.view.View.MeasureSpec.makeMeasureSpec; -import static org.isoron.androidbase.utils.InterfaceUtils.getDimension; -import static org.isoron.androidbase.utils.InterfaceUtils.getFontAwesome; -import static org.isoron.uhabits.core.models.Checkmark.CHECKED_EXPLICITLY; -import static org.isoron.uhabits.core.models.Checkmark.UNCHECKED; -import static org.isoron.uhabits.utils.AttributeSetUtils.getIntAttribute; - -public class CheckmarkButtonView extends View -{ - private int color; - - private int value; - - private StyledResources styledRes; - - private TextPaint paint; - - private int lowContrastColor; - - private RectF rect; - - @Nullable - private Preferences prefs; - - @NonNull - private OnToggleListener onToggleListener; - - @NonNull - private OnInvalidToggleListener onInvalidToggleListener; - - public CheckmarkButtonView(@Nullable Context context) - { - super(context); - init(); - } - - public CheckmarkButtonView(@Nullable Context ctx, @Nullable AttributeSet attrs) - { - super(ctx, attrs); - init(); - - if(ctx == null) throw new IllegalStateException(); - if(attrs == null) throw new IllegalStateException(); - - int paletteColor = getIntAttribute(ctx, attrs, "color", 0); - setColor(PaletteUtils.getAndroidTestColor(paletteColor)); - int value = getIntAttribute(ctx, attrs, "value", 0); - setValue(value); - } - - public void setColor(int color) - { - this.color = color; - postInvalidate(); - } - - public void setValue(int value) - { - this.value = value; - postInvalidate(); - } - - public void performToggle() - { - onToggleListener.onToggle(); - value = (value == CHECKED_EXPLICITLY ? UNCHECKED : CHECKED_EXPLICITLY); - performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - postInvalidate(); - } - - @Override - protected void onDraw(Canvas canvas) - { - super.onDraw(canvas); - Resources resources = getResources(); - - paint.setColor(value == CHECKED_EXPLICITLY ? color : lowContrastColor); - int id = (value == UNCHECKED ? R.string.fa_times : R.string.fa_check); - String label = resources.getString(id); - float em = paint.measureText("m"); - - rect.set(0, 0, getWidth(), getHeight()); - rect.offset(0, 0.4f * em); - canvas.drawText(label, rect.centerX(), rect.centerY(), paint); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) - { - Resources res = getResources(); - int height = res.getDimensionPixelSize(R.dimen.checkmarkHeight); - int width = res.getDimensionPixelSize(R.dimen.checkmarkWidth); - - widthMeasureSpec = makeMeasureSpec(width, EXACTLY); - heightMeasureSpec = makeMeasureSpec(height, EXACTLY); - - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } - - private void init() - { - setFocusable(false); - - styledRes = new StyledResources(getContext()); - - paint = new TextPaint(); - paint.setTypeface(getFontAwesome(getContext())); - paint.setAntiAlias(true); - paint.setTextAlign(Paint.Align.CENTER); - paint.setTextSize(getDimension(getContext(), R.dimen.smallTextSize)); - - rect = new RectF(); - color = Color.BLACK; - lowContrastColor = styledRes.getColor(R.attr.lowContrastTextColor); - - onToggleListener = () -> {}; - onInvalidToggleListener = () -> {}; - - if (getContext() instanceof HabitsActivity) - { - HabitsApplicationComponent component = - ((HabitsActivity) getContext()).getAppComponent(); - prefs = component.getPreferences(); - } - - setOnClickListener((v) -> { - if (prefs == null) return; - if (prefs.isShortToggleEnabled()) performToggle(); - else onInvalidToggleListener.onInvalidToggle(); - }); - - setOnLongClickListener(v -> { - performToggle(); - return true; - }); - } - - public void setOnInvalidToggleListener( - @NonNull OnInvalidToggleListener onInvalidToggleListener) - { - this.onInvalidToggleListener = onInvalidToggleListener; - } - - public void setOnToggleListener(@NonNull OnToggleListener onToggleListener) - { - this.onToggleListener = onToggleListener; - } - - public interface OnInvalidToggleListener - { - void onInvalidToggle(); - } - - public interface OnToggleListener - { - void onToggle(); - } -} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt new file mode 100644 index 000000000..77981995a --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt @@ -0,0 +1,123 @@ +/* + * 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.list.views + +import android.content.* +import android.graphics.* +import android.text.* +import android.view.* +import android.view.View.MeasureSpec.* +import com.google.auto.factory.* +import org.isoron.androidbase.activities.* +import org.isoron.uhabits.* +import org.isoron.uhabits.core.models.Checkmark.* +import org.isoron.uhabits.core.preferences.* +import org.isoron.uhabits.utils.* + +@AutoFactory +class CheckmarkButtonView( + @Provided @ActivityContext context: Context, + @Provided val preferences: Preferences +) : View(context), + View.OnClickListener, + View.OnLongClickListener { + + var color: Int = Color.BLACK + set(value) { + field = value + invalidate() + } + + var value: Int = 0 + set(value) { + field = value + invalidate() + } + + var onToggle: () -> Unit = {} + private var drawer = Drawer() + + init { + isFocusable = false + setOnClickListener(this) + setOnLongClickListener(this) + } + + fun performToggle() { + onToggle() + value = when (value) { + CHECKED_EXPLICITLY -> UNCHECKED + else -> CHECKED_EXPLICITLY + } + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) + invalidate() + } + + override fun onClick(v: View) { + if (preferences.isShortToggleEnabled) performToggle() + else showMessage(R.string.long_press_to_toggle) + } + + override fun onLongClick(v: View): Boolean { + performToggle() + return true + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + drawer.draw(canvas) + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + val height = resources.getDimensionPixelSize(R.dimen.checkmarkHeight) + val width = resources.getDimensionPixelSize(R.dimen.checkmarkWidth) + super.onMeasure(width.toMeasureSpec(EXACTLY), + height.toMeasureSpec(EXACTLY)) + } + + private inner class Drawer { + private val rect = RectF() + private val lowContrastColor = sres.getColor(R.attr.lowContrastTextColor) + + private val paint = TextPaint().apply { + typeface = getFontAwesome() + isAntiAlias = true + textAlign = Paint.Align.CENTER + textSize = dim(R.dimen.smallTextSize) + } + + fun draw(canvas: Canvas) { + paint.color = when (value) { + CHECKED_EXPLICITLY -> color + else -> lowContrastColor + } + val id = when (value) { + UNCHECKED -> R.string.fa_times + else -> R.string.fa_check + } + val label = resources.getString(id) + val em = paint.measureText("m") + + rect.set(0f, 0f, width.toFloat(), height.toFloat()) + rect.offset(0f, 0.4f * em) + canvas.drawText(label, rect.centerX(), rect.centerY(), paint) + } + } +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.java deleted file mode 100644 index afec42462..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * 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.list.views; - -import android.content.*; -import android.support.annotation.*; -import android.util.*; -import android.widget.*; - -import org.isoron.uhabits.*; -import org.isoron.uhabits.core.preferences.*; -import org.isoron.uhabits.core.utils.*; - -import java.util.*; - -import static android.view.View.MeasureSpec.EXACTLY; -import static android.view.View.MeasureSpec.makeMeasureSpec; -import static org.isoron.androidbase.utils.InterfaceUtils.getDimension; -import static org.isoron.uhabits.utils.AttributeSetUtils.getIntAttribute; -import static org.isoron.uhabits.utils.PaletteUtils.getAndroidTestColor; - -public class CheckmarkPanelView extends LinearLayout - implements Preferences.Listener -{ - private static final int LEFT_TO_RIGHT = 0; - - private static final int RIGHT_TO_LEFT = 1; - - @Nullable - private Preferences prefs; - - private int values[]; - - private int nButtons; - - private int color; - - private int dataOffset; - - @NonNull - private OnInvalidToggleListener onInvalidToggleListener; - - @NonNull - private OnToggleListener onToggleLister; - - public CheckmarkPanelView(Context context) - { - super(context); - init(); - } - - public CheckmarkPanelView(Context ctx, AttributeSet attrs) - { - super(ctx, attrs); - init(); - - if (ctx != null && attrs != null) - { - int paletteColor = getIntAttribute(ctx, attrs, "color", 0); - setColor(getAndroidTestColor(paletteColor)); - setButtonCount(getIntAttribute(ctx, attrs, "button_count", 5)); - } - - if (isInEditMode()) initEditMode(); - } - - public CheckmarkButtonView indexToButton(int i) - { - int position = i; - - if (getCheckmarkOrder() == RIGHT_TO_LEFT) position = nButtons - i - 1; - - return (CheckmarkButtonView) getChildAt(position); - } - - @Override - public void onCheckmarkOrderChanged() - { - setupButtons(); - } - - public void setButtonCount(int newButtonCount) - { - if (nButtons != newButtonCount) - { - nButtons = newButtonCount; - addButtons(); - } - - setupButtons(); - } - - public void setColor(int color) - { - this.color = color; - setupButtons(); - } - - public void setDataOffset(int dataOffset) - { - this.dataOffset = dataOffset; - setupButtons(); - } - - public void setOnInvalidToggleListener( - @NonNull OnInvalidToggleListener onInvalidToggleListener) - { - this.onInvalidToggleListener = onInvalidToggleListener; - } - - public void setOnToggleLister(@NonNull OnToggleListener onToggleLister) - { - this.onToggleLister = onToggleLister; - } - - public void setValues(int[] values) - { - this.values = values; - setupButtons(); - } - - @Override - protected void onAttachedToWindow() - { - super.onAttachedToWindow(); - if (prefs != null) prefs.addListener(this); - } - - @Override - protected void onDetachedFromWindow() - { - if (prefs != null) prefs.removeListener(this); - super.onDetachedFromWindow(); - } - - @Override - protected void onMeasure(int widthSpec, int heightSpec) - { - float buttonWidth = getDimension(getContext(), R.dimen.checkmarkWidth); - float buttonHeight = - getDimension(getContext(), R.dimen.checkmarkHeight); - - float width = buttonWidth * nButtons; - - widthSpec = makeMeasureSpec((int) width, EXACTLY); - heightSpec = makeMeasureSpec((int) buttonHeight, EXACTLY); - - super.onMeasure(widthSpec, heightSpec); - } - - private void addButtons() - { - removeAllViews(); - - for (int i = 0; i < nButtons; i++) - addView(new CheckmarkButtonView(getContext())); - } - - private int getCheckmarkOrder() - { - if (prefs == null) return LEFT_TO_RIGHT; - return prefs.shouldReverseCheckmarks() ? RIGHT_TO_LEFT : LEFT_TO_RIGHT; - } - - private void init() - { - Context appContext = getContext().getApplicationContext(); - if (appContext instanceof HabitsApplication) - { - HabitsApplication app = (HabitsApplication) appContext; - prefs = app.getComponent().getPreferences(); - } - - onInvalidToggleListener = () -> {}; - onToggleLister = (t) -> {}; - - setWillNotDraw(false); - values = new int[0]; - } - - private void initEditMode() - { - int values[] = new int[nButtons]; - - for (int i = 0; i < nButtons; i++) - values[i] = Math.min(2, new Random().nextInt(4)); - - setValues(values); - } - - private void setupButtonControllers(long timestamp, - CheckmarkButtonView buttonView) - { - buttonView.setOnInvalidToggleListener( - () -> onInvalidToggleListener.onInvalidToggle()); - buttonView.setOnToggleListener( - () -> onToggleLister.onToggle(timestamp)); - } - - private void setupButtons() - { - long timestamp = DateUtils.getStartOfToday(); - long day = DateUtils.millisecondsInOneDay; - timestamp -= day * dataOffset; - - for (int i = 0; i < nButtons; i++) - { - CheckmarkButtonView buttonView = indexToButton(i); - if (i + dataOffset >= values.length) break; - buttonView.setValue(values[i + dataOffset]); - buttonView.setColor(color); - setupButtonControllers(timestamp, buttonView); - timestamp -= day; - } - } - - public interface OnInvalidToggleListener - { - void onInvalidToggle(); - } - - public interface OnToggleListener - { - void onToggle(long timestamp); - } -} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt new file mode 100644 index 000000000..30d81a379 --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt @@ -0,0 +1,71 @@ +/* + * 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.list.views + +import android.content.* +import com.google.auto.factory.* +import org.isoron.androidbase.activities.* +import org.isoron.uhabits.core.models.Checkmark.* +import org.isoron.uhabits.core.preferences.* +import org.isoron.uhabits.core.utils.* + +@AutoFactory +class CheckmarkPanelView( + @Provided @ActivityContext context: Context, + @Provided preferences: Preferences, + @Provided private val buttonFactory: CheckmarkButtonViewFactory +) : ButtonPanelView(context, preferences) { + + var values = IntArray(0) + set(values) { + field = values + setupButtons() + } + + var color = 0 + set(value) { + field = value + setupButtons() + } + + var onToggle: (Long) -> Unit = {} + set(value) { + field = value + setupButtons() + } + + override fun createButton(): CheckmarkButtonView = buttonFactory.create() + + @Synchronized + override fun setupButtons() { + val today = DateUtils.getStartOfToday() + val day = DateUtils.millisecondsInOneDay + + buttons.forEachIndexed { index, button -> + val timestamp = today - (index + dataOffset) * day + button.value = when { + index + dataOffset < values.size -> values[index + dataOffset] + else -> UNCHECKED + } + button.color = color + button.onToggle = { onToggle(timestamp) } + } + } +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/EmptyListView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/EmptyListView.kt new file mode 100644 index 000000000..3d4ddafb1 --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/EmptyListView.kt @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2017 Á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.list.views + +import android.content.* +import android.view.* +import android.view.Gravity.* +import android.view.ViewGroup.LayoutParams.* +import android.widget.* +import org.isoron.androidbase.activities.* +import org.isoron.uhabits.* +import org.isoron.uhabits.utils.* + +class EmptyListView(context: Context) : LinearLayout(context) { + init { + orientation = VERTICAL + gravity = Gravity.CENTER + visibility = BaseRootView.GONE + + addView(TextView(context).apply { + text = str(R.string.fa_star_half_o) + typeface = getFontAwesome() + textSize = sp(40.0f) + gravity = CENTER + setTextColor(sres.getColor(R.attr.mediumContrastTextColor)) + }, MATCH_PARENT, WRAP_CONTENT) + + addView(TextView(context).apply { + text = str(R.string.no_habits_found) + gravity = CENTER + setPadding(0, dp(20.0f).toInt(), 0, 0) + setTextColor(sres.getColor(R.attr.mediumContrastTextColor)) + }, MATCH_PARENT, WRAP_CONTENT) + } +} \ No newline at end of file diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListAdapter.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListAdapter.java index 76598a64d..6992391c1 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListAdapter.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListAdapter.java @@ -78,7 +78,8 @@ public HabitCardListAdapter(@NonNull HabitCardListCache cache, this.midnightTimer = midnightTimer; cache.setListener(this); - cache.setCheckmarkCount(ListHabitsRootView.MAX_CHECKMARK_COUNT); + cache.setCheckmarkCount( + ListHabitsRootViewKt.MAX_CHECKMARK_COUNT); cache.setOrder(preferences.getDefaultOrder()); setHasStableIds(true); @@ -202,7 +203,7 @@ public HabitCardViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (listView == null) return null; - View view = listView.createCardView(); + View view = listView.createHabitCardView(); return new HabitCardViewHolder(view); } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListController.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListController.java deleted file mode 100644 index 86d1d1bd9..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListController.java +++ /dev/null @@ -1,334 +0,0 @@ -/* - * 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.list.views; - -import android.support.annotation.*; - -import org.isoron.androidbase.activities.*; -import org.isoron.uhabits.core.models.*; - -import javax.inject.*; - -/** - * Controller responsible for receiving and processing the events generated by a - * HabitListView. These include selecting and reordering items, toggling - * checkmarks and clicking habits. - */ -@ActivityScope -public class HabitCardListController implements HabitCardListView.Controller, - ModelObservable.Listener -{ - private final Mode NORMAL_MODE = new NormalMode(); - - private final Mode SELECTION_MODE = new SelectionMode(); - - @NonNull - private final HabitCardListAdapter adapter; - - @Nullable - private HabitListener habitListener; - - @Nullable - private SelectionListener selectionListener; - - @NonNull - private Mode activeMode; - - @Inject - public HabitCardListController(@NonNull HabitCardListAdapter adapter) - { - this.adapter = adapter; - this.activeMode = new NormalMode(); - adapter.getObservable().addListener(this); - } - - /** - * Called when the user drags a habit and drops it somewhere. Note that the - * dragging operation is already complete. - * - * @param from the original position of the habit - * @param to the position where the habit was released - */ - @Override - public void drop(int from, int to) - { - if (from == to) return; - cancelSelection(); - - Habit habitFrom = adapter.getItem(from); - Habit habitTo = adapter.getItem(to); - adapter.performReorder(from, to); - - if (habitListener != null) - habitListener.onHabitReorder(habitFrom, habitTo); - } - - @Override - public void onEdit(@NonNull Habit habit, long timestamp) - { - if (habitListener != null) habitListener.onEdit(habit, timestamp); - } - - @Override - public void onInvalidEdit() - { - if (habitListener != null) habitListener.onInvalidEdit(); - } - - /** - * Called when the user attempts to perform a toggle, but attempt is - * rejected. - */ - @Override - public void onInvalidToggle() - { - if (habitListener != null) habitListener.onInvalidToggle(); - } - - /** - * Called when the user clicks at some item. - * - * @param position the position of the clicked item - */ - @Override - public void onItemClick(int position) - { - activeMode.onItemClick(position); - } - - /** - * Called when the user long clicks at some item. - * - * @param position the position of the clicked item - */ - @Override - public void onItemLongClick(int position) - { - activeMode.onItemLongClick(position); - } - - @Override - public void onModelChange() - { - if(adapter.isSelectionEmpty()) - { - activeMode = new NormalMode(); - if (selectionListener != null) selectionListener.onSelectionFinish(); - } - } - - /** - * Called when the selection operation is cancelled externally, by something - * other than this controller. This happens, for example, when the user - * presses the back button. - */ - public void onSelectionFinished() - { - cancelSelection(); - } - - /** - * Called when the user wants to toggle a checkmark. - * - * @param habit the habit of the checkmark - * @param timestamp the timestamps of the checkmark - */ - @Override - public void onToggle(@NonNull Habit habit, long timestamp) - { - if (habitListener != null) habitListener.onToggle(habit, timestamp); - } - - public void setHabitListener(@Nullable HabitListener habitListener) - { - this.habitListener = habitListener; - } - - public void setSelectionListener(@Nullable SelectionListener listener) - { - this.selectionListener = listener; - } - - /** - * Called when the user starts dragging an item. - * - * @param position the position of the habit dragged - */ - @Override - public void startDrag(int position) - { - activeMode.startDrag(position); - } - - /** - * Selects or deselects the item at a given position - * - * @param position the position of the item to be selected/deselected - */ - protected void toggleSelection(int position) - { - adapter.toggleSelection(position); - activeMode = adapter.isSelectionEmpty() ? NORMAL_MODE : SELECTION_MODE; - } - - /** - * Marks all items as not selected and finishes the selection operation. - */ - private void cancelSelection() - { - adapter.clearSelection(); - activeMode = new NormalMode(); - if (selectionListener != null) selectionListener.onSelectionFinish(); - } - - public interface HabitListener - { - void onEdit(Habit habit, long timestamp); - - /** - * Called when the user clicks a habit. - * - * @param habit the habit clicked - */ - void onHabitClick(@NonNull Habit habit); - - /** - * Called when the user wants to change the position of a habit on the - * list. - * - * @param from habit to be moved - * @param to habit that currently occupies the desired position - */ - void onHabitReorder(@NonNull Habit from, @NonNull Habit to); - - void onInvalidEdit(); - - void onInvalidToggle(); - - void onToggle(Habit habit, long timestamp); - } - - /** - * A Mode describes the behaviour of the list upon clicking, long clicking - * and dragging an item. This depends on whether some items are already - * selected or not. - */ - private interface Mode - { - void onItemClick(int position); - - boolean onItemLongClick(int position); - - void startDrag(int position); - } - - public interface SelectionListener - { - /** - * Called when the user changes the list of selected item. This is only - * called if there were previously selected items. If the selection was - * previously empty, then onHabitSelectionStart is called instead. - */ - void onSelectionChange(); - - /** - * Called when the user deselects all items or cancels the selection. - */ - void onSelectionFinish(); - - /** - * Called after the user selects the first item. - */ - void onSelectionStart(); - } - - /** - * Mode activated when there are no items selected. Clicks trigger habit - * click. Long clicks start selection. - */ - class NormalMode implements Mode - { - @Override - public void onItemClick(int position) - { - Habit habit = adapter.getItem(position); - if (habitListener != null) habitListener.onHabitClick(habit); - } - - @Override - public boolean onItemLongClick(int position) - { - startSelection(position); - return true; - } - - @Override - public void startDrag(int position) - { - startSelection(position); - } - - protected void startSelection(int position) - { - toggleSelection(position); - activeMode = SELECTION_MODE; - if (selectionListener != null) selectionListener.onSelectionStart(); - } - } - - /** - * Mode activated when some items are already selected. - *

- * Clicks toggle item selection. Long clicks select more items. - */ - class SelectionMode implements Mode - { - @Override - public void onItemClick(int position) - { - toggleSelection(position); - notifyListener(); - } - - @Override - public boolean onItemLongClick(int position) - { - toggleSelection(position); - notifyListener(); - return true; - } - - @Override - public void startDrag(int position) - { - toggleSelection(position); - notifyListener(); - } - - protected void notifyListener() - { - if (selectionListener == null) return; - - if (activeMode == SELECTION_MODE) - selectionListener.onSelectionChange(); - else selectionListener.onSelectionFinish(); - } - } -} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListController.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListController.kt new file mode 100644 index 000000000..b68f3b24c --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListController.kt @@ -0,0 +1,167 @@ +/* + * 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.list.views + +import dagger.* +import org.isoron.androidbase.activities.* +import org.isoron.uhabits.activities.habits.list.* +import org.isoron.uhabits.core.models.* +import org.isoron.uhabits.core.ui.screens.habits.list.* +import javax.inject.* + +/** + * Controller responsible for receiving and processing the events generated by a + * HabitListView. These include selecting and reordering items, toggling + * checkmarks and clicking habits. + */ +@ActivityScope +class HabitCardListController @Inject constructor( + private val adapter: HabitCardListAdapter, + private val behavior: ListHabitsBehavior, + private val selectionMenu: Lazy +) : HabitCardListView.Controller, ModelObservable.Listener { + + private val NORMAL_MODE = NormalMode() + private val SELECTION_MODE = SelectionMode() + private var activeMode: Mode + + init { + this.activeMode = NORMAL_MODE + adapter.observable.addListener(this) + } + + override fun drop(from: Int, to: Int) { + if (from == to) return + cancelSelection() + + val habitFrom = adapter.getItem(from) + val habitTo = adapter.getItem(to) + if(habitFrom == null || habitTo == null) return + + adapter.performReorder(from, to) + behavior.onReorderHabit(habitFrom, habitTo) + } + + override fun onItemClick(position: Int) { + activeMode.onItemClick(position) + } + + override fun onItemLongClick(position: Int) { + activeMode.onItemLongClick(position) + } + + override fun onModelChange() { + if (adapter.isSelectionEmpty) { + activeMode = NormalMode() + selectionMenu.get().onSelectionFinish() + } + } + + fun onSelectionFinished() { + cancelSelection() + } + + override fun startDrag(position: Int) { + activeMode.startDrag(position) + } + + protected fun toggleSelection(position: Int) { + adapter.toggleSelection(position) + activeMode = if (adapter.isSelectionEmpty) NORMAL_MODE else SELECTION_MODE + } + + private fun cancelSelection() { + adapter.clearSelection() + activeMode = NormalMode() + selectionMenu.get().onSelectionFinish() + } + + interface HabitListener { + fun onHabitClick(habit: Habit) + fun onHabitReorder(from: Habit, to: Habit) + } + + /** + * A Mode describes the behavior of the list upon clicking, long clicking + * and dragging an item. This depends on whether some items are already + * selected or not. + */ + private interface Mode { + fun onItemClick(position: Int) + fun onItemLongClick(position: Int): Boolean + fun startDrag(position: Int) + } + + /** + * Mode activated when there are no items selected. Clicks trigger habit + * click. Long clicks start selection. + */ + internal inner class NormalMode : Mode { + override fun onItemClick(position: Int) { + val habit = adapter.getItem(position) + if (habit == null) return + behavior.onClickHabit(habit) + } + + override fun onItemLongClick(position: Int): Boolean { + startSelection(position) + return true + } + + override fun startDrag(position: Int) { + startSelection(position) + } + + protected fun startSelection(position: Int) { + toggleSelection(position) + activeMode = SELECTION_MODE + selectionMenu.get().onSelectionStart() + } + } + + /** + * Mode activated when some items are already selected. Clicks toggle + * item selection. Long clicks select more items. + */ + internal inner class SelectionMode : Mode { + override fun onItemClick(position: Int) { + toggleSelection(position) + notifyListener() + } + + override fun onItemLongClick(position: Int): Boolean { + toggleSelection(position) + notifyListener() + return true + } + + override fun startDrag(position: Int) { + toggleSelection(position) + notifyListener() + } + + protected fun notifyListener() { + if (activeMode === SELECTION_MODE) + selectionMenu.get().onSelectionChange() + else + selectionMenu.get().onSelectionFinish() + } + } +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.java deleted file mode 100644 index 5de5f8a0f..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.java +++ /dev/null @@ -1,282 +0,0 @@ -/* - * 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.list.views; - -import android.content.*; -import android.os.*; -import android.support.annotation.*; -import android.support.v7.widget.*; -import android.support.v7.widget.helper.*; -import android.util.*; -import android.view.*; - -import org.isoron.uhabits.activities.common.views.*; -import org.isoron.uhabits.core.models.*; - -import java.util.*; - -public class HabitCardListView extends RecyclerView -{ - @Nullable - private HabitCardListAdapter adapter; - - @NonNull - private Controller controller; - - private final ItemTouchHelper touchHelper; - - private int checkmarkCount; - - private int dataOffset; - - private LinkedList attachedHolders; - - public HabitCardListView(Context context, AttributeSet attrs) - { - super(context, attrs); - setLongClickable(true); - setHasFixedSize(true); - setLayoutManager(new LinearLayoutManager(getContext())); - - TouchHelperCallback callback = new TouchHelperCallback(); - touchHelper = new ItemTouchHelper(callback); - touchHelper.attachToRecyclerView(this); - - attachedHolders = new LinkedList<>(); - controller = new Controller() {}; - } - - public void attachCardView(HabitCardViewHolder holder) - { - attachedHolders.add(holder); - } - - /** - * Builds a new HabitCardView to be eventually added to this list, - * containing the given data. - * - * @param holder the ViewHolder containing the HabitCardView that should - * be built - * @param habit the habit for this card - * @param score the current score for the habit - * @param checkmarks the list of checkmark values to be included in the - * card - * @param selected true if the card is selected, false otherwise - * @return the HabitCardView generated - */ - public View bindCardView(@NonNull HabitCardViewHolder holder, - @NonNull Habit habit, - double score, - int[] checkmarks, - boolean selected) - { - HabitCardView cardView = (HabitCardView) holder.itemView; - cardView.setHabit(habit); - cardView.setSelected(selected); - cardView.setValues(checkmarks); - cardView.setButtonCount(checkmarkCount); - cardView.setDataOffset(dataOffset); - cardView.setScore(score); - cardView.setUnit(habit.getUnit()); - cardView.setThreshold(habit.getTargetValue()); - setupCardViewListeners(holder); - return cardView; - } - - public View createCardView() - { - return new HabitCardView(getContext()); - } - - public void detachCardView(HabitCardViewHolder holder) - { - attachedHolders.remove(holder); - } - - @Override - public void setAdapter(RecyclerView.Adapter adapter) - { - this.adapter = (HabitCardListAdapter) adapter; - super.setAdapter(adapter); - } - - public void setCheckmarkCount(int checkmarkCount) - { - this.checkmarkCount = checkmarkCount; - } - - public void setController(@NonNull Controller controller) - { - this.controller = controller; - } - - public void setDataOffset(int dataOffset) - { - this.dataOffset = dataOffset; - for (HabitCardViewHolder holder : attachedHolders) - { - HabitCardView cardView = (HabitCardView) holder.itemView; - cardView.setDataOffset(dataOffset); - } - } - - @Override - protected void onAttachedToWindow() - { - super.onAttachedToWindow(); - if (adapter != null) adapter.onAttached(); - } - - @Override - protected void onDetachedFromWindow() - { - if (adapter != null) adapter.onDetached(); - super.onDetachedFromWindow(); - } - - @Override - protected void onRestoreInstanceState(Parcelable state) - { - if(!(state instanceof BundleSavedState)) - { - super.onRestoreInstanceState(state); - return; - } - - BundleSavedState bss = (BundleSavedState) state; - dataOffset = bss.bundle.getInt("dataOffset"); - super.onRestoreInstanceState(bss.getSuperState()); - } - - @Override - protected Parcelable onSaveInstanceState() - { - Parcelable superState = super.onSaveInstanceState(); - Bundle bundle = new Bundle(); - bundle.putInt("dataOffset", dataOffset); - return new BundleSavedState(superState, bundle); - } - - protected void setupCardViewListeners(@NonNull HabitCardViewHolder holder) - { - HabitCardView cardView = (HabitCardView) holder.itemView; - cardView.setOnInvalidEditListener(() -> controller.onInvalidEdit()); - cardView.setOnInvalidToggleListener(() -> controller.onInvalidToggle()); - cardView.setOnToggleListener( - (habit, timestamp) -> controller.onToggle(habit, timestamp)); - cardView.setOnEditListener( - (habit, timestamp) -> controller.onEdit(habit, timestamp)); - - GestureDetector detector = new GestureDetector(getContext(), - new CardViewGestureDetector(holder)); - - cardView.setOnTouchListener((v, ev) -> { - detector.onTouchEvent(ev); - return true; - }); - } - - public interface Controller - { - default void drop(int from, int to) {} - - default void onItemClick(int pos) {} - - default void onItemLongClick(int pos) {} - - default void startDrag(int position) {} - - default void onInvalidToggle() {} - - default void onInvalidEdit() {} - - default void onToggle(@NonNull Habit habit, long timestamp) {} - - default void onEdit(@NonNull Habit habit, long timestamp) {} - } - - private class CardViewGestureDetector - extends GestureDetector.SimpleOnGestureListener - { - @NonNull - private final HabitCardViewHolder holder; - - public CardViewGestureDetector(@NonNull HabitCardViewHolder holder) - { - this.holder = holder; - } - - @Override - public void onLongPress(MotionEvent e) - { - int position = holder.getAdapterPosition(); - if (controller != null) controller.onItemLongClick(position); - if (adapter.isSortable()) touchHelper.startDrag(holder); - } - - @Override - public boolean onSingleTapUp(MotionEvent e) - { - int position = holder.getAdapterPosition(); - if (controller != null) controller.onItemClick(position); - return true; - } - } - - class TouchHelperCallback extends ItemTouchHelper.Callback - { - @Override - public int getMovementFlags(RecyclerView recyclerView, - ViewHolder viewHolder) - { - int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; - int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END; - return makeMovementFlags(dragFlags, swipeFlags); - } - - @Override - public boolean isItemViewSwipeEnabled() - { - return false; - } - - @Override - public boolean isLongPressDragEnabled() - { - return false; - } - - @Override - public boolean onMove(RecyclerView recyclerView, - ViewHolder from, - ViewHolder to) - { - if (controller == null) return false; - controller.drop(from.getAdapterPosition(), to.getAdapterPosition()); - return true; - } - - @Override - public void onSwiped(ViewHolder viewHolder, int direction) - { - // NOP - } - } -} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.kt new file mode 100644 index 000000000..c68d56d5a --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.kt @@ -0,0 +1,171 @@ +/* + * 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.list.views + +import android.content.* +import android.os.* +import android.support.v7.widget.* +import android.support.v7.widget.helper.* +import android.support.v7.widget.helper.ItemTouchHelper.* +import android.view.* +import com.google.auto.factory.* +import dagger.* +import org.isoron.androidbase.activities.* +import org.isoron.uhabits.activities.common.views.* +import org.isoron.uhabits.core.models.* + +@AutoFactory +class HabitCardListView( + @Provided @ActivityContext context: Context, + @Provided private val adapter: HabitCardListAdapter, + @Provided private val cardViewFactory: HabitCardViewFactory, + @Provided private val controller: Lazy +) : RecyclerView(context) { + + var checkmarkCount: Int = 0 + + var dataOffset: Int = 0 + set(value) { + field = value + attachedHolders + .map { it.itemView as HabitCardView } + .forEach { it.dataOffset = value } + } + + private val attachedHolders = mutableListOf() + private val touchHelper = ItemTouchHelper(TouchHelperCallback()).apply { + attachToRecyclerView(this@HabitCardListView) + } + + init { + setHasFixedSize(true) + isLongClickable = true + layoutManager = LinearLayoutManager(context) + super.setAdapter(adapter) + } + + fun createHabitCardView(): View { + return cardViewFactory.create() + } + + fun bindCardView(holder: HabitCardViewHolder, + habit: Habit, + score: Double, + checkmarks: IntArray, + selected: Boolean): View { + val cardView = holder.itemView as HabitCardView + cardView.habit = habit + cardView.isSelected = selected + cardView.values = checkmarks + cardView.buttonCount = checkmarkCount + cardView.dataOffset = dataOffset + cardView.score = score + cardView.unit = habit.unit + cardView.threshold = habit.targetValue + + val detector = GestureDetector(context, CardViewGestureDetector(holder)) + cardView.setOnTouchListener { _, ev -> + detector.onTouchEvent(ev) + true + } + + return cardView + } + + fun attachCardView(holder: HabitCardViewHolder) { + attachedHolders.add(holder) + } + + fun detachCardView(holder: HabitCardViewHolder) { + attachedHolders.remove(holder) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + adapter.onAttached() + } + + override fun onDetachedFromWindow() { + adapter.onDetached() + super.onDetachedFromWindow() + } + + override fun onRestoreInstanceState(state: Parcelable) { + if (state !is BundleSavedState) { + super.onRestoreInstanceState(state) + return + } + dataOffset = state.bundle.getInt("dataOffset") + super.onRestoreInstanceState(state.superState) + } + + override fun onSaveInstanceState(): Parcelable { + val superState = super.onSaveInstanceState() + val bundle = Bundle().apply { + putInt("dataOffset", dataOffset) + } + return BundleSavedState(superState, bundle) + } + + interface Controller { + fun drop(from: Int, to: Int) {} + fun onItemClick(pos: Int) {} + fun onItemLongClick(pos: Int) {} + fun startDrag(position: Int) {} + } + + private inner class CardViewGestureDetector( + private val holder: HabitCardViewHolder + ) : GestureDetector.SimpleOnGestureListener() { + + override fun onLongPress(e: MotionEvent) { + val position = holder.adapterPosition + controller.get().onItemLongClick(position) + if (adapter.isSortable) touchHelper.startDrag(holder) + } + + override fun onSingleTapUp(e: MotionEvent): Boolean { + val position = holder.adapterPosition + controller.get().onItemClick(position) + return true + } + } + + inner class TouchHelperCallback : ItemTouchHelper.Callback() { + override fun getMovementFlags(recyclerView: RecyclerView, + viewHolder: RecyclerView.ViewHolder): Int { + return makeMovementFlags(UP or DOWN, START or END) + } + + override fun onMove(recyclerView: RecyclerView, + from: RecyclerView.ViewHolder, + to: RecyclerView.ViewHolder): Boolean { + controller.get().drop(from.adapterPosition, to.adapterPosition) + return true + } + + override fun onSwiped(viewHolder: RecyclerView.ViewHolder, + direction: Int) { + } + + override fun isItemViewSwipeEnabled() = false + override fun isLongPressDragEnabled() = false + } +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.java deleted file mode 100644 index 4c9bbc332..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.java +++ /dev/null @@ -1,406 +0,0 @@ -/* - * 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.list.views; - -import android.annotation.*; -import android.content.*; -import android.graphics.drawable.*; -import android.os.*; -import android.support.annotation.*; -import android.text.*; -import android.util.*; -import android.view.*; -import android.widget.*; - -import org.isoron.androidbase.utils.*; -import org.isoron.uhabits.*; -import org.isoron.uhabits.activities.common.views.*; -import org.isoron.uhabits.core.models.*; -import org.isoron.uhabits.core.utils.*; -import org.isoron.uhabits.utils.*; - -import java.util.*; - -import static android.os.Build.VERSION.SDK_INT; -import static android.os.Build.VERSION_CODES.LOLLIPOP; -import static android.os.Build.VERSION_CODES.M; -import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; -import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; -import static org.isoron.androidbase.utils.InterfaceUtils.dpToPixels; - -public class HabitCardView extends FrameLayout - implements ModelObservable.Listener -{ - private static final String EDIT_MODE_HABITS[] = { - "Wake up early", - "Wash dishes", - "Exercise", - "Meditate", - "Play guitar", - "Wash clothes", - "Get a haircut" - }; - - CheckmarkPanelView checkmarkPanel; - - NumberPanelView numberPanel; - - LinearLayout innerFrame; - - TextView label; - - RingView scoreRing; - - private final Context context = getContext(); - - private StyledResources res; - - @Nullable - private Habit habit; - - private int dataOffset; - - @NonNull - OnInvalidEditListener onInvalidEditListener; - - @NonNull - OnEditListener onEditListener; - - @NonNull - private OnToggleListener onToggleListener; - - @NonNull - private OnInvalidToggleListener onInvalidToggleListener; - - public HabitCardView(Context context) - { - super(context); - init(); - } - - public HabitCardView(Context context, AttributeSet attrs) - { - super(context, attrs); - init(); - } - - @Override - public void onModelChange() - { - new Handler(Looper.getMainLooper()).post(() -> refresh()); - } - - public void setButtonCount(int buttonCount) - { - checkmarkPanel.setButtonCount(buttonCount); - numberPanel.setButtonCount(buttonCount); - } - - public void setDataOffset(int dataOffset) - { - this.dataOffset = dataOffset; - checkmarkPanel.setDataOffset(dataOffset); - numberPanel.setDataOffset(dataOffset); - } - - public void setHabit(@NonNull Habit habit) - { - if (isAttachedToWindow()) stopListening(); - this.habit = habit; - refresh(); - if (isAttachedToWindow()) startListening(); - postInvalidate(); - } - - public void setScore(double score) - { - float percentage = (float) score; - scoreRing.setPercentage(percentage); - scoreRing.setPrecision(1.0f / 16); - postInvalidate(); - } - - @Override - public void setSelected(boolean isSelected) - { - super.setSelected(isSelected); - updateBackground(isSelected); - } - - public void setThreshold(double threshold) - { - numberPanel.setThreshold(threshold); - } - - public void setUnit(String unit) - { - numberPanel.setUnit(unit); - } - - public void setValues(int values[]) - { - double dvalues[] = new double[values.length]; - for (int i = 0; i < values.length; i++) - dvalues[i] = (double) values[i] / 1000; - - checkmarkPanel.setValues(values); - numberPanel.setValues(dvalues); - numberPanel.setThreshold(10); - postInvalidate(); - } - - public void triggerRipple(long timestamp) - { - long today = DateUtils.getStartOfToday(); - long day = DateUtils.millisecondsInOneDay; - int offset = (int) ((today - timestamp) / day) - dataOffset; - CheckmarkButtonView button = checkmarkPanel.indexToButton(offset); - - float y = button.getHeight() / 2.0f; - float x = checkmarkPanel.getX() + button.getX() + button.getWidth() / 2; - triggerRipple(x, y); - } - - @Override - protected void onAttachedToWindow() - { - super.onAttachedToWindow(); - stopListening(); - } - - @Override - protected void onDetachedFromWindow() - { - startListening(); - super.onDetachedFromWindow(); - } - - private int getActiveColor(Habit habit) - { - int mediumContrastColor = res.getColor(R.attr.mediumContrastTextColor); - int activeColor = PaletteUtils.getColor(context, habit.getColor()); - if (habit.isArchived()) activeColor = mediumContrastColor; - - return activeColor; - } - - private void init() - { - res = new StyledResources(getContext()); - setLayoutParams(new LayoutParams(MATCH_PARENT, WRAP_CONTENT)); - setClipToPadding(false); - - int margin = (int) dpToPixels(context, 3); - setPadding(margin, 0, margin, margin); - - initInnerFrame(); - initScoreRing(); - initLabel(); - - onInvalidEditListener = () -> {}; - onInvalidToggleListener = () -> {}; - onEditListener = ((h, t) -> {}); - onToggleListener = ((h,t) -> {}); - - checkmarkPanel = new CheckmarkPanelView(context); - checkmarkPanel.setOnToggleLister( - (t) -> onToggleListener.onToggle(habit, t)); - checkmarkPanel.setOnInvalidToggleListener( - () -> onInvalidToggleListener.onInvalidToggle()); - - numberPanel = new NumberPanelView(context); - numberPanel.setVisibility(GONE); - numberPanel.setOnInvalidEditListener(() -> - onInvalidEditListener.onInvalidEdit()); - numberPanel.setOnEditListener(((t) -> { - triggerRipple(t); - onEditListener.onEdit(habit, t); - })); - - innerFrame.addView(scoreRing); - innerFrame.addView(label); - innerFrame.addView(checkmarkPanel); - innerFrame.addView(numberPanel); - addView(innerFrame); - - innerFrame.setOnTouchListener((v, event) -> - { - if (SDK_INT >= LOLLIPOP) - v.getBackground().setHotspot(event.getX(), event.getY()); - return false; - }); - - if (isInEditMode()) initEditMode(); - } - - @SuppressLint("SetTextI18n") - private void initEditMode() - { - Random rand = new Random(); - int color = PaletteUtils.getAndroidTestColor(rand.nextInt(10)); - label.setText(EDIT_MODE_HABITS[rand.nextInt(EDIT_MODE_HABITS.length)]); - label.setTextColor(color); - scoreRing.setColor(color); - scoreRing.setPercentage(rand.nextFloat()); - checkmarkPanel.setColor(color); - numberPanel.setColor(color); - checkmarkPanel.setButtonCount(5); - } - - private void initInnerFrame() - { - LinearLayout.LayoutParams params; - params = new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT); - - innerFrame = new LinearLayout(context); - innerFrame.setLayoutParams(params); - innerFrame.setOrientation(LinearLayout.HORIZONTAL); - innerFrame.setGravity(Gravity.CENTER_VERTICAL); - - if (SDK_INT >= LOLLIPOP) - innerFrame.setElevation(dpToPixels(context, 1)); - } - - private void initLabel() - { - LinearLayout.LayoutParams params; - params = new LinearLayout.LayoutParams(0, WRAP_CONTENT, 1); - - label = new TextView(context); - label.setLayoutParams(params); - label.setMaxLines(2); - label.setEllipsize(TextUtils.TruncateAt.END); - - if (SDK_INT >= M) - label.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED); - } - - private void initScoreRing() - { - scoreRing = new RingView(context); - int ringSize = (int) dpToPixels(context, 15); - int margin = (int) dpToPixels(context, 8); - float thickness = dpToPixels(context, 3); - - LinearLayout.LayoutParams params; - params = new LinearLayout.LayoutParams(ringSize, ringSize); - params.setMargins(margin, 0, margin, 0); - params.gravity = Gravity.CENTER; - - scoreRing.setLayoutParams(params); - scoreRing.setThickness(thickness); - } - - private void refresh() - { - int color = getActiveColor(habit); - label.setText(habit.getName()); - label.setTextColor(color); - scoreRing.setColor(color); - checkmarkPanel.setColor(color); - numberPanel.setColor(color); - - boolean isNumerical = habit.isNumerical(); - checkmarkPanel.setVisibility(isNumerical ? GONE : VISIBLE); - numberPanel.setVisibility(isNumerical ? VISIBLE : GONE); - - postInvalidate(); - } - - private void startListening() - { - if (habit != null) habit.getObservable().removeListener(this); - } - - private void stopListening() - { - if (habit != null) habit.getObservable().addListener(this); - } - - private void triggerRipple(final float x, final float y) - { - final Drawable background = innerFrame.getBackground(); - if (SDK_INT >= LOLLIPOP) background.setHotspot(x, y); - background.setState(new int[]{ - android.R.attr.state_pressed, android.R.attr.state_enabled - }); - new Handler().postDelayed(() -> background.setState(new int[]{}), 25); - } - - private void updateBackground(boolean isSelected) - { - if (SDK_INT >= LOLLIPOP) - { - if (isSelected) - innerFrame.setBackgroundResource(R.drawable.selected_box); - else innerFrame.setBackgroundResource(R.drawable.ripple); - } - else - { - Drawable background; - if (isSelected) - background = res.getDrawable(R.attr.selectedBackground); - else background = res.getDrawable(R.attr.cardBackground); - innerFrame.setBackgroundDrawable(background); - } - } - - public void setOnEditListener(@NonNull OnEditListener onEditListener) - { - this.onEditListener = onEditListener; - } - - public void setOnInvalidEditListener( - @NonNull OnInvalidEditListener onInvalidEditListener) - { - this.onInvalidEditListener = onInvalidEditListener; - } - - public void setOnToggleListener(@NonNull OnToggleListener onToggleListener) - { - this.onToggleListener = onToggleListener; - } - - public void setOnInvalidToggleListener( - @NonNull OnInvalidToggleListener onInvalidToggleListener) - { - this.onInvalidToggleListener = onInvalidToggleListener; - } - - public interface OnEditListener - { - void onEdit(@NonNull Habit habit, long timestamp); - } - - public interface OnInvalidEditListener - { - void onInvalidEdit(); - } - - public interface OnInvalidToggleListener - { - void onInvalidToggle(); - } - - public interface OnToggleListener - { - void onToggle(@NonNull Habit habit, long timestamp); - } -} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt new file mode 100644 index 000000000..f948266de --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt @@ -0,0 +1,253 @@ +/* + * 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.list.views + +import android.content.* +import android.os.* +import android.os.Build.VERSION.* +import android.os.Build.VERSION_CODES.* +import android.text.* +import android.view.* +import android.view.ViewGroup.LayoutParams.* +import android.widget.* +import com.google.auto.factory.* +import org.isoron.androidbase.activities.* +import org.isoron.uhabits.* +import org.isoron.uhabits.activities.common.views.* +import org.isoron.uhabits.core.models.* +import org.isoron.uhabits.core.ui.screens.habits.list.* +import org.isoron.uhabits.core.utils.* +import org.isoron.uhabits.utils.* + +@AutoFactory +class HabitCardView( + @Provided @ActivityContext context: Context, + @Provided private val checkmarkPanelFactory: CheckmarkPanelViewFactory, + @Provided private val numberPanelFactory: NumberPanelViewFactory, + @Provided private val behavior: ListHabitsBehavior +) : FrameLayout(context), + ModelObservable.Listener { + + var buttonCount + get() = checkmarkPanel.buttonCount + set(value) { + checkmarkPanel.buttonCount = value + numberPanel.buttonCount = value + } + + var dataOffset = 0 + set(value) { + field = value + checkmarkPanel.dataOffset = value + numberPanel.dataOffset = value + } + + var habit: Habit? = null + set(newHabit) { + if (isAttachedToWindow) { + field?.observable?.removeListener(this) + newHabit?.observable?.addListener(this) + } + field = newHabit + if (newHabit != null) copyAttributesFrom(newHabit) + } + + var score + get() = scoreRing.percentage.toDouble() + set(value) { + scoreRing.percentage = value.toFloat() + scoreRing.precision = 1.0f / 16 + } + + var unit + get() = numberPanel.units + set(value) { + numberPanel.units = value + } + + var values + get() = checkmarkPanel.values + set(values) { + checkmarkPanel.values = values + numberPanel.values = values.map { it / 1000.0 }.toDoubleArray() + } + + var threshold: Double + get() = numberPanel.threshold + set(value) { + numberPanel.threshold = value + } + + private var checkmarkPanel: CheckmarkPanelView + private var numberPanel: NumberPanelView + private var innerFrame: LinearLayout + private var label: TextView + private var scoreRing: RingView + + init { + scoreRing = RingView(context).apply { + val thickness = dp(3f) + val margin = dp(8f).toInt() + val ringSize = dp(15f).toInt() + layoutParams = LinearLayout.LayoutParams(ringSize, ringSize).apply { + setMargins(margin, 0, margin, 0) + gravity = Gravity.CENTER + } + setThickness(thickness) + } + + label = TextView(context).apply { + maxLines = 2 + ellipsize = TextUtils.TruncateAt.END + layoutParams = LinearLayout.LayoutParams(0, WRAP_CONTENT, 1f) + if (SDK_INT >= M) breakStrategy = Layout.BREAK_STRATEGY_BALANCED + } + + checkmarkPanel = checkmarkPanelFactory.create().apply { + onToggle = { timestamp -> + triggerRipple(timestamp) + habit?.let { behavior.onToggle(it, timestamp) } + } + } + + numberPanel = numberPanelFactory.create().apply { + visibility = GONE + onEdit = { timestamp -> + triggerRipple(timestamp) + habit?.let { behavior.onEdit(it, timestamp) } + } + } + + innerFrame = LinearLayout(context).apply { + gravity = Gravity.CENTER_VERTICAL + orientation = LinearLayout.HORIZONTAL + layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT) + if (SDK_INT >= LOLLIPOP) elevation = dp(1f) + + addView(scoreRing) + addView(label) + addView(checkmarkPanel) + addView(numberPanel) + + setOnTouchListener { v, event -> + if (SDK_INT >= LOLLIPOP) + v.background.setHotspot(event.x, event.y) + false + } + } + + clipToPadding = false + layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT) + val margin = dp(3f).toInt() + setPadding(margin, 0, margin, margin) + addView(innerFrame) + } + + override fun onModelChange() { + Handler(Looper.getMainLooper()).post { + habit?.let { copyAttributesFrom(it) } + } + } + + override fun setSelected(isSelected: Boolean) { + super.setSelected(isSelected) + updateBackground(isSelected) + } + + fun triggerRipple(timestamp: Long) { + val today = DateUtils.getStartOfToday() + val day = DateUtils.millisecondsInOneDay + val offset = ((today - timestamp) / day).toInt() - dataOffset + val button = checkmarkPanel.buttons[offset] + val y = button.height / 2.0f + val x = checkmarkPanel.x + button.x + (button.width / 2).toFloat() + triggerRipple(x, y) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + habit?.observable?.addListener(this) + } + + override fun onDetachedFromWindow() { + habit?.observable?.removeListener(this) + super.onDetachedFromWindow() + } + + private fun copyAttributesFrom(h: Habit) { + + fun getActiveColor(habit: Habit): Int { + return when (habit.isArchived) { + true -> sres.getColor(R.attr.mediumContrastTextColor) + false -> PaletteUtils.getColor(context, habit.color) + } + } + + val c = getActiveColor(h) + label.apply { + text = h.name + setTextColor(c) + } + scoreRing.apply { + color = c + } + checkmarkPanel.apply { + color = c + visibility = when (h.isNumerical) { + true -> View.GONE + false -> View.VISIBLE + } + } + numberPanel.apply { + color = c + units = h.unit + threshold = h.targetValue + visibility = when (h.isNumerical) { + true -> View.VISIBLE + false -> View.GONE + } + } + } + + private fun triggerRipple(x: Float, y: Float) { + val background = innerFrame.background + if (SDK_INT >= LOLLIPOP) background.setHotspot(x, y) + background.state = intArrayOf(android.R.attr.state_pressed, + android.R.attr.state_enabled) + Handler().postDelayed({ background.state = intArrayOf() }, 25) + } + + private fun updateBackground(isSelected: Boolean) { + if (SDK_INT < LOLLIPOP) { + val background = when (isSelected) { + true -> sres.getDrawable(R.attr.selectedBackground) + false -> sres.getDrawable(R.attr.cardBackground) + } + innerFrame.setBackgroundDrawable(background) + return + } + + val background = when (isSelected) { + true -> R.drawable.selected_box + false -> R.drawable.ripple + } + innerFrame.setBackgroundResource(background) + } +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/tasks/package-info.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardViewHolder.kt similarity index 80% rename from uhabits-android/src/main/java/org/isoron/uhabits/tasks/package-info.java rename to uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardViewHolder.kt index 5a175d814..ca820109c 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/tasks/package-info.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardViewHolder.kt @@ -17,8 +17,9 @@ * with this program. If not, see . */ -/** - * Provides async tasks for useful operations such as {@link - * org.isoron.uhabits.core.tasks.ExportCSVTask}. - */ -package org.isoron.uhabits.tasks; \ No newline at end of file +package org.isoron.uhabits.activities.habits.list.views + +import android.support.v7.widget.* +import android.view.* + +class HabitCardViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HeaderView.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HeaderView.java deleted file mode 100644 index 90bdebf39..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HeaderView.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * 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.list.views; - -import android.content.*; -import android.graphics.*; -import android.support.annotation.*; -import android.text.*; -import android.util.*; - -import org.isoron.androidbase.utils.*; -import org.isoron.uhabits.*; -import org.isoron.uhabits.activities.common.views.*; -import org.isoron.uhabits.core.preferences.*; -import org.isoron.uhabits.core.utils.*; - -import java.util.*; - -import static org.isoron.androidbase.utils.InterfaceUtils.*; - -public class HeaderView extends ScrollableChart - implements Preferences.Listener, MidnightTimer.MidnightListener -{ - - private int buttonCount; - - @Nullable - private Preferences prefs; - - @Nullable - private MidnightTimer midnightTimer; - - private TextPaint paint; - - private RectF rect; - - public HeaderView(@NonNull Context context, - @NonNull Preferences prefs, - @NonNull MidnightTimer midnightTimer) - { - super(context); - this.prefs = prefs; - this.midnightTimer = midnightTimer; - init(); - } - - public HeaderView(Context context, @Nullable AttributeSet attrs) - { - super(context, attrs); - - Context appContext = context.getApplicationContext(); - if (appContext instanceof HabitsApplication) - { - HabitsApplication app = (HabitsApplication) appContext; - prefs = app.getComponent().getPreferences(); - midnightTimer = app.getComponent().getMidnightTimer(); - } - - init(); - } - - @Override - public void atMidnight() - { - post(() -> invalidate()); - } - - @Override - public void onCheckmarkOrderChanged() - { - updateDirection(); - postInvalidate(); - } - - public void setButtonCount(int buttonCount) - { - this.buttonCount = buttonCount; - postInvalidate(); - } - - @Override - protected void onAttachedToWindow() - { - updateDirection(); - super.onAttachedToWindow(); - if (prefs != null) prefs.addListener(this); - if (midnightTimer != null) midnightTimer.addListener(this); - } - - @Override - protected void onDetachedFromWindow() - { - if (midnightTimer != null) midnightTimer.removeListener(this); - if (prefs != null) prefs.removeListener(this); - super.onDetachedFromWindow(); - } - - @Override - protected void onDraw(Canvas canvas) - { - super.onDraw(canvas); - - GregorianCalendar day = DateUtils.getStartOfTodayCalendar(); - float width = getDimension(getContext(), R.dimen.checkmarkWidth); - float height = getDimension(getContext(), R.dimen.checkmarkHeight); - boolean reverse = shouldReverseCheckmarks(); - boolean isRtl = InterfaceUtils.isLayoutRtl(this); - - day.add(GregorianCalendar.DAY_OF_MONTH, -getDataOffset()); - float em = paint.measureText("m"); - - for (int i = 0; i < buttonCount; i++) - { - rect.set(0, 0, width, height); - rect.offset(canvas.getWidth(), 0); - - if (reverse) rect.offset(-(i + 1) * width, 0); - else rect.offset((i - buttonCount) * width, 0); - - if (isRtl) rect.set(canvas.getWidth() - rect.right, rect.top, - canvas.getWidth() - rect.left, rect.bottom); - - String text = DateUtils.formatHeaderDate(day).toUpperCase(); - String[] lines = text.split("\n"); - - int y1 = (int) (rect.centerY() - 0.25 * em); - int y2 = (int) (rect.centerY() + 1.25 * em); - - canvas.drawText(lines[0], rect.centerX(), y1, paint); - canvas.drawText(lines[1], rect.centerX(), y2, paint); - day.add(GregorianCalendar.DAY_OF_MONTH, -1); - } - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) - { - int width = MeasureSpec.getSize(widthMeasureSpec); - int height = (int) getDimension(getContext(), R.dimen.checkmarkHeight); - setMeasuredDimension(width, height); - } - - private void init() - { - setScrollerBucketSize( - (int) getDimension(getContext(), R.dimen.checkmarkWidth)); - - StyledResources sr = new StyledResources(getContext()); - paint = new TextPaint(); - paint.setColor(Color.BLACK); - paint.setAntiAlias(true); - paint.setTextSize(getDimension(getContext(), R.dimen.tinyTextSize)); - paint.setTextAlign(Paint.Align.CENTER); - paint.setTypeface(Typeface.DEFAULT_BOLD); - paint.setColor(sr.getColor(R.attr.mediumContrastTextColor)); - - rect = new RectF(); - - if (isInEditMode()) setButtonCount(5); - } - - private boolean shouldReverseCheckmarks() - { - if (prefs == null) return false; - return prefs.shouldReverseCheckmarks(); - } - - private void updateDirection() - { - int direction = -1; - if (shouldReverseCheckmarks()) direction *= -1; - if (InterfaceUtils.isLayoutRtl(this)) direction *= -1; - setDirection(direction); - } -} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HeaderView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HeaderView.kt new file mode 100644 index 000000000..e5c057f55 --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HeaderView.kt @@ -0,0 +1,136 @@ +/* + * 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.list.views + +import android.content.* +import android.graphics.* +import android.os.Build.VERSION.* +import android.os.Build.VERSION_CODES.* +import android.text.* +import android.view.View.MeasureSpec.* +import org.isoron.uhabits.* +import org.isoron.uhabits.activities.common.views.* +import org.isoron.uhabits.core.preferences.* +import org.isoron.uhabits.core.utils.* +import org.isoron.uhabits.core.utils.DateUtils.* +import org.isoron.uhabits.utils.* +import java.util.* + +class HeaderView( + context: Context, + val prefs: Preferences, + val midnightTimer: MidnightTimer +) : ScrollableChart(context), + Preferences.Listener, + MidnightTimer.MidnightListener { + + private var drawer = Drawer() + + var buttonCount: Int = 0 + set(value) { + field = value + requestLayout() + } + + init { + setScrollerBucketSize(dim(R.dimen.checkmarkWidth).toInt()) + setBackgroundColor(sres.getColor(R.attr.headerBackgroundColor)) + if (SDK_INT >= LOLLIPOP) elevation = dp(2.0f) + } + + override fun atMidnight() { + post { invalidate() } + } + + override fun onCheckmarkSequenceChanged() { + updateScrollDirection() + postInvalidate() + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + updateScrollDirection() + prefs.addListener(this) + midnightTimer.addListener(this) + } + + override fun onDetachedFromWindow() { + midnightTimer.removeListener(this) + prefs.removeListener(this) + super.onDetachedFromWindow() + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + drawer.draw(canvas) + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + val height = dim(R.dimen.checkmarkHeight) + setMeasuredDimension(widthMeasureSpec, height.toMeasureSpec(EXACTLY)) + } + + private fun updateScrollDirection() { + var direction = -1 + if (prefs.isCheckmarkSequenceReversed) direction *= -1 + if (isRTL()) direction *= -1 + setScrollDirection(direction) + } + + private inner class Drawer { + private val rect = RectF() + private val paint = TextPaint().apply { + color = Color.BLACK + isAntiAlias = true + textSize = dim(R.dimen.tinyTextSize) + textAlign = Paint.Align.CENTER + typeface = Typeface.DEFAULT_BOLD + color = sres.getColor(R.attr.mediumContrastTextColor) + } + + fun draw(canvas: Canvas) { + val day = getStartOfTodayCalendar() + val width = dim(R.dimen.checkmarkWidth) + val height = dim(R.dimen.checkmarkHeight) + val isReversed = prefs.isCheckmarkSequenceReversed + + day.add(GregorianCalendar.DAY_OF_MONTH, -dataOffset) + val em = paint.measureText("m") + + repeat(buttonCount) { index -> + rect.set(0f, 0f, width, height) + rect.offset(canvas.width.toFloat(), 0f) + + if (isReversed) rect.offset(-(index + 1) * width, 0f) + else rect.offset((index - buttonCount) * width, 0f) + + if (isRTL()) rect.set(canvas.width - rect.right, rect.top, + canvas.width - rect.left, rect.bottom) + + val y1 = rect.centerY() - 0.25 * em + val y2 = rect.centerY() + 1.25 * em + val lines = formatHeaderDate(day).toUpperCase().split("\n") + canvas.drawText(lines[0], rect.centerX(), y1.toFloat(), paint) + canvas.drawText(lines[1], rect.centerX(), y2.toFloat(), paint) + day.add(GregorianCalendar.DAY_OF_MONTH, -1) + } + } + } +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HintView.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HintView.java deleted file mode 100644 index 1848b4827..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HintView.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * 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.list.views; - -import android.animation.AnimatorListenerAdapter; -import android.annotation.SuppressLint; -import android.content.Context; -import android.support.annotation.Nullable; -import android.util.AttributeSet; -import android.view.View; -import android.widget.FrameLayout; -import android.widget.TextView; - -import org.isoron.uhabits.R; -import org.isoron.uhabits.core.ui.screens.habits.list.HintList; - -import java.util.Random; - -import butterknife.BindView; -import butterknife.ButterKnife; - -public class HintView extends FrameLayout -{ - @BindView(R.id.hintContent) - TextView hintContent; - - @Nullable - private HintList hintList; - - public HintView(Context context) - { - super(context); - init(); - } - - public HintView(Context context, AttributeSet attrs) - { - super(context, attrs); - init(); - } - - @Override - public void onAttachedToWindow() - { - super.onAttachedToWindow(); - showNext(); - } - - /** - * Sets the list of hints to be shown - * - * @param hintList the list of hints to be shown - */ - public void setHints(@Nullable HintList hintList) - { - this.hintList = hintList; - } - - private void dismiss() - { - animate().alpha(0f).setDuration(500).setListener(new DismissAnimator()); - } - - private void init() - { - addView(inflate(getContext(), R.layout.list_habits_hint, null)); - ButterKnife.bind(this); - - setVisibility(GONE); - setClickable(true); - setOnClickListener(v -> dismiss()); - - if (isInEditMode()) initEditMode(); - } - - @SuppressLint("SetTextI18n") - private void initEditMode() - { - String hints[] = { - "Cats are the most popular pet in the United States: There " + - "are 88 million pet cats and 74 million dogs.", - "A cat has been mayor of Talkeetna, Alaska, for 15 years. " + - "His name is Stubbs.", - "Cats can’t taste sweetness." - }; - - int k = new Random().nextInt(hints.length); - hintContent.setText(hints[k]); - setVisibility(VISIBLE); - setAlpha(1.0f); - } - - protected void showNext() - { - if (hintList == null) return; - if (!hintList.shouldShow()) return; - - String hint = hintList.pop(); - if (hint == null) return; - - hintContent.setText(hint); - requestLayout(); - - setAlpha(0.0f); - setVisibility(View.VISIBLE); - animate().alpha(1f).setDuration(500); - } - - private class DismissAnimator extends AnimatorListenerAdapter - { - @Override - public void onAnimationEnd(android.animation.Animator animation) - { - setVisibility(View.GONE); - } - } -} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HintView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HintView.kt new file mode 100644 index 000000000..8bbbf8ea2 --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HintView.kt @@ -0,0 +1,91 @@ +/* + * 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.list.views + +import android.animation.* +import android.content.* +import android.graphics.* +import android.graphics.Color.* +import android.view.* +import android.view.ViewGroup.LayoutParams.* +import android.widget.* +import org.isoron.uhabits.* +import org.isoron.uhabits.core.ui.screens.habits.list.* +import org.isoron.uhabits.utils.* + +class HintView( + context: Context, + private val hintList: HintList +) : LinearLayout(context) { + + val hintContent: TextView + + init { + isClickable = true + visibility = GONE + orientation = VERTICAL + val p1 = dp(16.0f).toInt() + val p2 = dp(4.0f).toInt() + setPadding(p1, p1, p2, p1) + setBackgroundColor(resources.getColor(R.color.indigo_500)) + + val hintTitle = TextView(context).apply { + setTextColor(WHITE) + setTypeface(null, Typeface.BOLD) + text = resources.getString(R.string.hint_title) + } + + hintContent = TextView(context).apply { + setTextColor(WHITE) + setPadding(0, dp(5.0f).toInt(), 0, 0) + } + + addView(hintTitle, WRAP_CONTENT, WRAP_CONTENT) + addView(hintContent, WRAP_CONTENT, WRAP_CONTENT) + setOnClickListener { dismiss() } + } + + public override fun onAttachedToWindow() { + super.onAttachedToWindow() + showNext() + } + + fun showNext() { + if (!hintList.shouldShow()) return + val hint = hintList.pop() ?: return + + hintContent.text = hint + requestLayout() + + alpha = 0.0f + visibility = View.VISIBLE + animate().alpha(1f).duration = 500 + } + + private fun dismiss() { + animate().alpha(0f).setDuration(500).setListener(DismissAnimator()) + } + + private inner class DismissAnimator : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: android.animation.Animator) { + visibility = View.GONE + } + } +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.java deleted file mode 100644 index db625cafc..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * 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.list.views; - -import android.content.*; -import android.graphics.*; -import android.support.annotation.*; -import android.text.*; -import android.util.*; -import android.view.*; - -import org.isoron.androidbase.utils.*; -import org.isoron.uhabits.*; -import org.isoron.uhabits.activities.*; -import org.isoron.uhabits.core.preferences.*; -import org.isoron.uhabits.utils.*; - -import java.text.*; - -import static org.isoron.androidbase.utils.InterfaceUtils.getDimension; -import static org.isoron.uhabits.utils.AttributeSetUtils.getAttribute; -import static org.isoron.uhabits.utils.AttributeSetUtils.getIntAttribute; - -public class NumberButtonView extends View implements View.OnClickListener, - View.OnLongClickListener -{ - private static Typeface BOLD_TYPEFACE = - Typeface.create("sans-serif-condensed", Typeface.BOLD); - - private static Typeface NORMAL_TYPEFACE = - Typeface.create("sans-serif-condensed", Typeface.NORMAL); - - private int color; - - private double value; - - private double threshold; - - private String unit; - - private RectF rect; - - private TextPaint pRegular; - - private TextPaint pBold; - - private int lightGrey; - - private float em; - - private int darkGrey; - - @NonNull - private OnEditListener onEditListener; - - @NonNull - private OnInvalidEditListener onInvalidEditListener; - - @Nullable - private Preferences prefs; - - public NumberButtonView(@Nullable Context context) - { - super(context); - init(); - } - - public NumberButtonView(@Nullable Context ctx, @Nullable AttributeSet attrs) - { - super(ctx, attrs); - init(); - - if (ctx != null && attrs != null) - { - int color = getIntAttribute(ctx, attrs, "color", 0); - int value = getIntAttribute(ctx, attrs, "value", 0); - int threshold = getIntAttribute(ctx, attrs, "threshold", 1); - String unit = getAttribute(ctx, attrs, "unit", "min"); - setColor(PaletteUtils.getAndroidTestColor(color)); - setThreshold(threshold); - setValue(value); - setUnit(unit); - } - } - - public static String formatValue(double v) - { - if (v >= 1e9) return String.format("%.1fG", v / 1e9); - if (v >= 1e8) return String.format("%.0fM", v / 1e6); - if (v >= 1e7) return String.format("%.1fM", v / 1e6); - if (v >= 1e6) return String.format("%.1fM", v / 1e6); - if (v >= 1e5) return String.format("%.0fk", v / 1e3); - if (v >= 1e4) return String.format("%.1fk", v / 1e3); - if (v >= 1e3) return String.format("%.1fk", v / 1e3); - if (v >= 1e2) return new DecimalFormat("#").format(v); - if (v >= 1e1) return new DecimalFormat("#.#").format(v); - return new DecimalFormat("#.##").format(v); - } - - @Override - public void onClick(View v) - { - if(prefs == null) return; - if (prefs.isShortToggleEnabled()) onEditListener.onEdit(); - else onInvalidEditListener.onInvalidEdit(); - } - - @Override - public boolean onLongClick(View v) - { - onEditListener.onEdit(); - return true; - } - - public void setColor(int color) - { - this.color = color; - postInvalidate(); - } - - public void setThreshold(double threshold) - { - this.threshold = threshold; - postInvalidate(); - } - - public void setUnit(String unit) - { - this.unit = unit; - postInvalidate(); - } - - public void setValue(double value) - { - this.value = value; - postInvalidate(); - } - - public void setOnEditListener(@NonNull OnEditListener onEditListener) - { - this.onEditListener = onEditListener; - } - - public void setOnInvalidEditListener( - @NonNull OnInvalidEditListener onInvalidEditListener) - { - this.onInvalidEditListener = onInvalidEditListener; - } - - @Override - protected void onDraw(Canvas canvas) - { - int activeColor = lightGrey; - if (value > 0 && value < threshold) activeColor = darkGrey; - if (value >= threshold) activeColor = color; - - pRegular.setColor(activeColor); - pBold.setColor(activeColor); - - String fv = formatValue(value); - - rect.set(0, 0, getWidth(), getHeight()); - canvas.drawText(fv, rect.centerX(), rect.centerY(), pBold); - - rect.offset(0, 1.2f * em); - canvas.drawText(unit, rect.centerX(), rect.centerY(), pRegular); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) - { - int width = (int) getDimension(getContext(), R.dimen.checkmarkWidth); - int height = (int) getDimension(getContext(), R.dimen.checkmarkHeight); - setMeasuredDimension(width, height); - } - - private void init() - { - StyledResources sr = new StyledResources(getContext()); - - rect = new RectF(); - pRegular = new TextPaint(); - pRegular.setTextSize( - getDimension(getContext(), R.dimen.smallerTextSize)); - pRegular.setTypeface(NORMAL_TYPEFACE); - pRegular.setAntiAlias(true); - pRegular.setTextAlign(Paint.Align.CENTER); - - pBold = new TextPaint(); - pBold.setTextSize(getDimension(getContext(), R.dimen.smallTextSize)); - pBold.setTypeface(BOLD_TYPEFACE); - pBold.setAntiAlias(true); - pBold.setTextAlign(Paint.Align.CENTER); - - em = pBold.measureText("m"); - lightGrey = sr.getColor(R.attr.lowContrastTextColor); - darkGrey = sr.getColor(R.attr.mediumContrastTextColor); - - onEditListener = () -> {}; - onInvalidEditListener = () -> {}; - - setOnClickListener(this); - setOnLongClickListener(this); - - if(getContext() instanceof HabitsActivity) - { - HabitsApplicationComponent component = - ((HabitsActivity) getContext()).getAppComponent(); - prefs = component.getPreferences(); - } - } - - public interface OnEditListener - { - void onEdit(); - } - - public interface OnInvalidEditListener - { - void onInvalidEdit(); - } -} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt new file mode 100644 index 000000000..53defd457 --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt @@ -0,0 +1,160 @@ +/* + * 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.list.views + +import android.content.* +import android.graphics.* +import android.text.* +import android.view.* +import android.view.View.* +import com.google.auto.factory.* +import org.isoron.androidbase.activities.* +import org.isoron.androidbase.utils.* +import org.isoron.androidbase.utils.InterfaceUtils.* +import org.isoron.uhabits.* +import org.isoron.uhabits.core.preferences.* +import org.isoron.uhabits.utils.* +import java.text.* + +private val BOLD_TYPEFACE = Typeface.create("sans-serif-condensed", Typeface.BOLD) +private val NORMAL_TYPEFACE = Typeface.create("sans-serif-condensed", Typeface.NORMAL) + +fun Double.toShortString(): String = when { + this >= 1e9 -> String.format("%.1fG", this / 1e9) + this >= 1e8 -> String.format("%.0fM", this / 1e6) + this >= 1e7 -> String.format("%.1fM", this / 1e6) + this >= 1e6 -> String.format("%.1fM", this / 1e6) + this >= 1e5 -> String.format("%.0fk", this / 1e3) + this >= 1e4 -> String.format("%.1fk", this / 1e3) + this >= 1e3 -> String.format("%.1fk", this / 1e3) + this >= 1e2 -> DecimalFormat("#").format(this) + this >= 1e1 -> DecimalFormat("#.#").format(this) + else -> DecimalFormat("#.##").format(this) +} + +@AutoFactory +class NumberButtonView( + @Provided @ActivityContext context: Context, + @Provided val preferences: Preferences +) : View(context), + OnClickListener, + OnLongClickListener { + + var color = 0 + set(value) { + field = value + invalidate() + } + + var value = 0.0 + set(value) { + field = value + invalidate() + } + + var threshold = 0.0 + set(value) { + field = value + invalidate() + } + + var units = "" + set(value) { + field = value + invalidate() + } + + var onEdit: () -> Unit = {} + private var drawer: Drawer = Drawer(context) + + init { + setOnClickListener(this) + setOnLongClickListener(this) + } + + override fun onClick(v: View) { + if (preferences.isShortToggleEnabled) onEdit() + else showMessage(R.string.long_press_to_edit) + } + + override fun onLongClick(v: View): Boolean { + onEdit() + return true + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + drawer.draw(canvas) + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + val width = getDimension(context, R.dimen.checkmarkWidth).toInt() + val height = getDimension(context, R.dimen.checkmarkHeight).toInt() + setMeasuredDimension(width, height) + } + + private inner class Drawer(context: Context) { + + private val em: Float + private val rect: RectF = RectF() + private val sr = StyledResources(context) + + private val lightGrey: Int + private val darkGrey: Int + + private val pRegular: TextPaint = TextPaint().apply { + textSize = getDimension(context, R.dimen.smallerTextSize) + typeface = NORMAL_TYPEFACE + isAntiAlias = true + textAlign = Paint.Align.CENTER + } + + private val pBold: TextPaint = TextPaint().apply { + textSize = getDimension(context, R.dimen.smallTextSize) + typeface = BOLD_TYPEFACE + isAntiAlias = true + textAlign = Paint.Align.CENTER + } + + init { + em = pBold.measureText("m") + lightGrey = sr.getColor(R.attr.lowContrastTextColor) + darkGrey = sr.getColor(R.attr.mediumContrastTextColor) + } + + fun draw(canvas: Canvas) { + val activeColor = when { + value == 0.0 -> lightGrey + value < threshold -> darkGrey + else -> color + } + + val label = value.toShortString() + pBold.color = activeColor + pRegular.color = activeColor + + rect.set(0f, 0f, width.toFloat(), height.toFloat()) + canvas.drawText(label, rect.centerX(), rect.centerY(), pBold) + + rect.offset(0f, 1.2f * em) + canvas.drawText(units, rect.centerX(), rect.centerY(), pRegular) + } + } +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.java deleted file mode 100644 index 80117bd58..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * 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.list.views; - -import android.content.*; -import android.support.annotation.*; -import android.util.*; -import android.widget.*; - -import org.isoron.uhabits.*; -import org.isoron.uhabits.core.preferences.*; -import org.isoron.uhabits.core.utils.*; - -import java.util.*; - -import static android.view.View.MeasureSpec.EXACTLY; -import static android.view.View.MeasureSpec.makeMeasureSpec; -import static org.isoron.androidbase.utils.InterfaceUtils.getDimension; -import static org.isoron.uhabits.utils.AttributeSetUtils.getAttribute; -import static org.isoron.uhabits.utils.AttributeSetUtils.getIntAttribute; -import static org.isoron.uhabits.utils.PaletteUtils.getAndroidTestColor; - -public class NumberPanelView extends LinearLayout - implements Preferences.Listener -{ - private static final int LEFT_TO_RIGHT = 0; - - private static final int RIGHT_TO_LEFT = 1; - - @Nullable - private Preferences prefs; - - private double values[]; - - private double threshold; - - private int nButtons; - - private int color; - - private String unit; - - private int dataOffset; - - @NonNull - private OnInvalidEditListener onInvalidEditListener; - - private OnEditListener onEditListener; - - public NumberPanelView(Context context) - { - super(context); - init(); - } - - public NumberPanelView(Context ctx, AttributeSet attrs) - { - super(ctx, attrs); - init(); - - if (ctx != null && attrs != null) - { - int paletteColor = getIntAttribute(ctx, attrs, "color", 0); - setColor(getAndroidTestColor(paletteColor)); - setButtonCount(getIntAttribute(ctx, attrs, "button_count", 5)); - setThreshold(getIntAttribute(ctx, attrs, "threshold", 1)); - setUnit(getAttribute(ctx, attrs, "unit", "min")); - } - - if (isInEditMode()) initEditMode(); - } - - public NumberButtonView indexToButton(int i) - { - int position = i; - if (getCheckmarkOrder() == RIGHT_TO_LEFT) position = nButtons - i - 1; - return (NumberButtonView) getChildAt(position); - } - - public void initEditMode() - { - double values[] = new double[nButtons]; - for (int i = 0; i < nButtons; i++) - values[i] = new Random().nextDouble() * (threshold * 3); - setValues(values); - } - - @Override - public void onCheckmarkOrderChanged() - { - setupButtons(); - } - - public void setButtonCount(int newButtonCount) - { - if (nButtons != newButtonCount) - { - nButtons = newButtonCount; - addButtons(); - } - - setupButtons(); - } - - public void setColor(int color) - { - this.color = color; - setupButtons(); - } - - public void setDataOffset(int dataOffset) - { - this.dataOffset = dataOffset; - setupButtons(); - } - - public void setOnInvalidEditListener( - @NonNull OnInvalidEditListener onInvalidEditListener) - { - this.onInvalidEditListener = onInvalidEditListener; - } - - public void setOnEditListener(OnEditListener onEditListener) - { - this.onEditListener = onEditListener; - } - - public void setThreshold(double threshold) - { - this.threshold = threshold; - setupButtons(); - } - - public void setUnit(String unit) - { - this.unit = unit; - setupButtons(); - } - - public void setValues(double[] values) - { - this.values = values; - setupButtons(); - } - - @Override - protected void onAttachedToWindow() - { - super.onAttachedToWindow(); - if (prefs != null) prefs.addListener(this); - } - - @Override - protected void onDetachedFromWindow() - { - if (prefs != null) prefs.removeListener(this); - super.onDetachedFromWindow(); - } - - @Override - protected void onMeasure(int widthSpec, int heightSpec) - { - Context context = getContext(); - float buttonWidth = getDimension(context, R.dimen.checkmarkWidth); - float buttonHeight = getDimension(context, R.dimen.checkmarkHeight); - - float width = buttonWidth * nButtons; - - widthSpec = makeMeasureSpec((int) width, EXACTLY); - heightSpec = makeMeasureSpec((int) buttonHeight, EXACTLY); - - super.onMeasure(widthSpec, heightSpec); - } - - private void addButtons() - { - removeAllViews(); - for (int i = 0; i < nButtons; i++) - addView(new NumberButtonView(getContext())); - } - - private int getCheckmarkOrder() - { - if (prefs == null) return LEFT_TO_RIGHT; - return prefs.shouldReverseCheckmarks() ? RIGHT_TO_LEFT : LEFT_TO_RIGHT; - } - - private void init() - { - Context appContext = getContext().getApplicationContext(); - if (appContext instanceof HabitsApplication) - { - HabitsApplication app = (HabitsApplication) appContext; - prefs = app.getComponent().getPreferences(); - } - - setWillNotDraw(false); - values = new double[0]; - - onInvalidEditListener = () -> {}; - onEditListener = (t) -> {}; - } - - private void setupButtonControllers(long timestamp, - NumberButtonView buttonView) - { - buttonView.setOnEditListener( - () -> onEditListener.onEdit(timestamp)); - - buttonView.setOnInvalidEditListener( - () -> onInvalidEditListener.onInvalidEdit()); - } - - private void setupButtons() - { - long timestamp = DateUtils.getStartOfToday(); - long day = DateUtils.millisecondsInOneDay; - timestamp -= day * dataOffset; - - for (int i = 0; i < nButtons; i++) - { - NumberButtonView buttonView = indexToButton(i); - if (i + dataOffset >= values.length) break; - buttonView.setValue(values[i + dataOffset]); - buttonView.setColor(color); - buttonView.setThreshold(threshold); - buttonView.setUnit(unit); - setupButtonControllers(timestamp, buttonView); - timestamp -= day; - } - } - - public interface OnInvalidEditListener - { - void onInvalidEdit(); - } - - public interface OnEditListener - { - void onEdit(long timestamp); - } -} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.kt new file mode 100644 index 000000000..aaaabc2a6 --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.kt @@ -0,0 +1,84 @@ +/* + * 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.list.views + +import android.content.* +import com.google.auto.factory.* +import org.isoron.androidbase.activities.* +import org.isoron.uhabits.core.preferences.* +import org.isoron.uhabits.core.utils.* + +@AutoFactory +class NumberPanelView( + @Provided @ActivityContext context: Context, + @Provided preferences: Preferences, + @Provided private val buttonFactory: NumberButtonViewFactory +) : ButtonPanelView(context, preferences) { + + var values = DoubleArray(0) + set(values) { + field = values + setupButtons() + } + + var threshold = 0.0 + set(value) { + field = value + setupButtons() + } + + var color = 0 + set(value) { + field = value + setupButtons() + } + + var units = "" + set(value) { + field = value + setupButtons() + } + + var onEdit: (Long) -> Unit = {} + set(value) { + field = value + setupButtons() + } + + override fun createButton() = buttonFactory.create()!! + + @Synchronized + override fun setupButtons() { + val day = DateUtils.millisecondsInOneDay + val today = DateUtils.getStartOfToday() + + buttons.forEachIndexed { index, button -> + val timestamp = today - (index + dataOffset) * day + button.value = when { + index + dataOffset < values.size -> values[index + dataOffset] + else -> 0.0 + } + button.color = color + button.threshold = threshold + button.units = units + button.onEdit = { onEdit(timestamp) } + } + } +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/ShadowView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/ShadowView.kt new file mode 100644 index 000000000..bc97fb198 --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/ShadowView.kt @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2017 Á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.list.views + +import android.content.* +import android.view.* +import android.view.View.MeasureSpec.* +import org.isoron.uhabits.* +import org.isoron.uhabits.utils.* + +@Suppress("DEPRECATION") +class ShadowView(context: Context) : View(context) { + init { + alpha = 0.2f + background = resources.getDrawable(R.drawable.shadow) + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + super.onMeasure(widthMeasureSpec, + dp(2.0f).toInt().toMeasureSpec(EXACTLY)) + } +} \ No newline at end of file diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.java index 42178f0ef..104056810 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.java @@ -34,6 +34,6 @@ public class ShowHabitActivity extends HabitsActivity protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setScreen(getActivityComponent().getShowHabitScreen()); + setScreen(getComponent().getShowHabitScreen()); } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/package-info.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/package-info.java deleted file mode 100644 index ca132a6c7..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/package-info.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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 . - */ - -/** - * Provides activity that displays detailed habit information and related - * classes. - */ -package org.isoron.uhabits.activities.habits.show; \ No newline at end of file diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/intro/package-info.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/intro/package-info.java deleted file mode 100644 index 4023d1b94..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/intro/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 . - */ - -/** - * Provides activity that introduces app to the user and related classes. - */ -package org.isoron.uhabits.activities.intro; \ No newline at end of file diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/package-info.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/package-info.java deleted file mode 100644 index abc95467c..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 . - */ - -/** - * Provides classes for the Android activites. - */ -package org.isoron.uhabits.activities; \ No newline at end of file diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/SettingsFragment.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/SettingsFragment.java index 07f4e062c..3badaac52 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/SettingsFragment.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/SettingsFragment.java @@ -39,11 +39,11 @@ import static android.media.RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT; import static android.media.RingtoneManager.EXTRA_RINGTONE_TYPE; import static android.media.RingtoneManager.TYPE_NOTIFICATION; -import static org.isoron.uhabits.activities.habits.list.ListHabitsScreen.RESULT_BUG_REPORT; -import static org.isoron.uhabits.activities.habits.list.ListHabitsScreen.RESULT_EXPORT_CSV; -import static org.isoron.uhabits.activities.habits.list.ListHabitsScreen.RESULT_EXPORT_DB; -import static org.isoron.uhabits.activities.habits.list.ListHabitsScreen.RESULT_IMPORT_DATA; -import static org.isoron.uhabits.activities.habits.list.ListHabitsScreen.RESULT_REPAIR_DB; +import static org.isoron.uhabits.activities.habits.list.ListHabitsScreenKt.RESULT_BUG_REPORT; +import static org.isoron.uhabits.activities.habits.list.ListHabitsScreenKt.RESULT_EXPORT_CSV; +import static org.isoron.uhabits.activities.habits.list.ListHabitsScreenKt.RESULT_EXPORT_DB; +import static org.isoron.uhabits.activities.habits.list.ListHabitsScreenKt.RESULT_IMPORT_DATA; +import static org.isoron.uhabits.activities.habits.list.ListHabitsScreenKt.RESULT_REPAIR_DB; public class SettingsFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/package-info.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/package-info.java deleted file mode 100644 index 73ed9c7a1..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 . - */ - -/** - * Provides activity for changing the settings. - */ -package org.isoron.uhabits.activities.settings; \ No newline at end of file diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/package-info.java b/uhabits-android/src/main/java/org/isoron/uhabits/package-info.java deleted file mode 100644 index b080842fc..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 . - */ - -/** - * Provides classes for the Loop Habit Tracker app. - */ -package org.isoron.uhabits; \ No newline at end of file diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/preferences/SharedPreferencesStorage.java b/uhabits-android/src/main/java/org/isoron/uhabits/preferences/SharedPreferencesStorage.java index 76b2a4c3b..7464a6992 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/preferences/SharedPreferencesStorage.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/preferences/SharedPreferencesStorage.java @@ -93,7 +93,7 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, switch (key) { case "pref_checkmark_reverse_order": - preferences.setShouldReverseCheckmarks(getBoolean(key, false)); + preferences.setCheckmarkSequenceReversed(getBoolean(key, false)); break; case "pref_sticky_notifications": diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/utils/ViewExtensions.kt b/uhabits-android/src/main/java/org/isoron/uhabits/utils/ViewExtensions.kt new file mode 100644 index 000000000..427bc5ba6 --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/utils/ViewExtensions.kt @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2017 Á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.utils + +import android.graphics.* +import android.support.annotation.* +import android.support.design.widget.* +import android.support.v7.widget.Toolbar +import android.view.* +import android.view.ViewGroup.LayoutParams.* +import android.widget.* +import android.widget.RelativeLayout.* +import org.isoron.androidbase.utils.* +import org.isoron.uhabits.* + +fun RelativeLayout.addBelow(view: View, + subject: View, + width: Int = MATCH_PARENT, + height: Int = WRAP_CONTENT, + applyCustomRules: (params: RelativeLayout.LayoutParams) -> Unit = {}) { + + view.layoutParams = RelativeLayout.LayoutParams(width, height).apply { + addRule(BELOW, subject.id) + applyCustomRules(this) + } + view.id = View.generateViewId() + this.addView(view) +} + +fun RelativeLayout.addAtBottom(view: View, + width: Int = MATCH_PARENT, + height: Int = WRAP_CONTENT) { + + view.layoutParams = RelativeLayout.LayoutParams(width, height).apply { + addRule(ALIGN_PARENT_BOTTOM) + } + view.id = View.generateViewId() + this.addView(view) +} + +fun RelativeLayout.addAtTop(view: View, + width: Int = MATCH_PARENT, + height: Int = WRAP_CONTENT) { + + view.layoutParams = RelativeLayout.LayoutParams(width, height).apply { + addRule(ALIGN_PARENT_TOP) + } + view.id = View.generateViewId() + this.addView(view) +} + +fun ViewGroup.buildToolbar(): Toolbar { + val inflater = LayoutInflater.from(context) + return inflater.inflate(R.layout.toolbar, null) as Toolbar +} + +fun View.showMessage(@StringRes stringId: Int) { + try { + val snackbar = Snackbar.make(this, stringId, Snackbar.LENGTH_SHORT) + val tvId = android.support.design.R.id.snackbar_text + val tv = snackbar.view.findViewById(tvId) + if(tv is TextView) tv.setTextColor(Color.WHITE) + snackbar.show() + } catch (e: IllegalArgumentException) { + return + } +} + +fun Int.toMeasureSpec(mode: Int) = + View.MeasureSpec.makeMeasureSpec(this, mode) + +fun Float.toMeasureSpec(mode: Int) = + View.MeasureSpec.makeMeasureSpec(toInt(), mode) + +fun View.isRTL() = InterfaceUtils.isLayoutRtl(this) +fun View.getFontAwesome() = InterfaceUtils.getFontAwesome(context)!! +fun View.dim(id: Int) = InterfaceUtils.getDimension(context, id) +fun View.sp(value: Float) = InterfaceUtils.spToPixels(context, value) +fun View.dp(value: Float) = InterfaceUtils.dpToPixels(context, value) +fun View.str(id: Int) = resources.getString(id) +val View.sres: StyledResources + get() = StyledResources(context) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/utils/package-info.java b/uhabits-android/src/main/java/org/isoron/uhabits/utils/package-info.java deleted file mode 100644 index 614727d39..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/utils/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 . - */ - -/** - * Provides various utilities classes, such as {@link org.isoron.androidbase.utils.ColorUtils}. - */ -package org.isoron.uhabits.utils; \ No newline at end of file diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/package-info.java b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/package-info.java deleted file mode 100644 index 5616e64ad..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 . - */ - -/** - * Provides home-screen Android widgets and related classes. - */ -package org.isoron.uhabits.widgets; \ No newline at end of file diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/package-info.java b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/package-info.java deleted file mode 100644 index 2fbf2799c..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 . - */ - -/** - * Provides views that are specific for the home-screen widgets. - */ -package org.isoron.uhabits.widgets.views; \ No newline at end of file diff --git a/uhabits-android/src/main/res/drawable/toolbar_shadow.xml b/uhabits-android/src/main/res/drawable/shadow.xml similarity index 100% rename from uhabits-android/src/main/res/drawable/toolbar_shadow.xml rename to uhabits-android/src/main/res/drawable/shadow.xml diff --git a/uhabits-android/src/main/res/layout/list_habits.xml b/uhabits-android/src/main/res/layout/list_habits.xml deleted file mode 100644 index 3515790a4..000000000 --- a/uhabits-android/src/main/res/layout/list_habits.xml +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/uhabits-android/src/main/res/layout/list_habits_button_preview.xml b/uhabits-android/src/main/res/layout/list_habits_button_preview.xml deleted file mode 100644 index 5f2724a07..000000000 --- a/uhabits-android/src/main/res/layout/list_habits_button_preview.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/uhabits-android/src/main/res/layout/list_habits_panel_preview.xml b/uhabits-android/src/main/res/layout/list_habits_panel_preview.xml deleted file mode 100644 index e20ca4438..000000000 --- a/uhabits-android/src/main/res/layout/list_habits_panel_preview.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/uhabits-android/src/main/res/layout/list_habits_preview.xml b/uhabits-android/src/main/res/layout/list_habits_preview.xml deleted file mode 100644 index 5ea6eb697..000000000 --- a/uhabits-android/src/main/res/layout/list_habits_preview.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/uhabits-android/src/main/res/layout/toolbar.xml b/uhabits-android/src/main/res/layout/toolbar.xml new file mode 100644 index 000000000..8d263e906 --- /dev/null +++ b/uhabits-android/src/main/res/layout/toolbar.xml @@ -0,0 +1,28 @@ + + + + \ No newline at end of file diff --git a/uhabits-android/src/main/res/values/styles.xml b/uhabits-android/src/main/res/values/styles.xml index 976ddf172..622fffe3e 100644 --- a/uhabits-android/src/main/res/values/styles.xml +++ b/uhabits-android/src/main/res/values/styles.xml @@ -237,7 +237,7 @@ diff --git a/uhabits-android/src/test/java/org/isoron/uhabits/BaseAndroidUnitTest.java b/uhabits-android/src/test/java/org/isoron/uhabits/BaseAndroidJVMTest.java similarity index 98% rename from uhabits-android/src/test/java/org/isoron/uhabits/BaseAndroidUnitTest.java rename to uhabits-android/src/test/java/org/isoron/uhabits/BaseAndroidJVMTest.java index f35f77ec4..a2f2c780d 100644 --- a/uhabits-android/src/test/java/org/isoron/uhabits/BaseAndroidUnitTest.java +++ b/uhabits-android/src/test/java/org/isoron/uhabits/BaseAndroidJVMTest.java @@ -34,16 +34,12 @@ import static org.mockito.Mockito.*; @RunWith(MockitoJUnitRunner.class) -public class BaseAndroidUnitTest +public class BaseAndroidJVMTest { protected HabitList habitList; - protected HabitFixtures fixtures; - protected MemoryModelFactory modelFactory; - protected SingleThreadTaskRunner taskRunner; - protected CommandRunner commandRunner; @Before diff --git a/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenuTest.java b/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenuTest.java deleted file mode 100644 index 8127343a5..000000000 --- a/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenuTest.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2017 Á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.list; - -import android.view.*; - -import org.isoron.androidbase.activities.*; -import org.isoron.uhabits.*; -import org.isoron.uhabits.R; -import org.isoron.uhabits.core.preferences.*; -import org.isoron.uhabits.core.ui.*; -import org.isoron.uhabits.core.ui.screens.habits.list.*; -import org.junit.*; - -import static org.mockito.Mockito.*; - -public class ListHabitsMenuTest extends BaseAndroidUnitTest -{ - private BaseActivity activity; - - private Preferences preferences; - - private ThemeSwitcher themeSwitcher; - - private ListHabitsMenu menu; - - private ListHabitsMenuBehavior behavior; - - @Before - @Override - public void setUp() - { - activity = mock(BaseActivity.class); - preferences = mock(Preferences.class); - themeSwitcher = mock(ThemeSwitcher.class); - behavior = mock(ListHabitsMenuBehavior.class); - - menu = new ListHabitsMenu(activity, preferences, - themeSwitcher, behavior); - } - - @Test - public void testOnCreate() - { - MenuItem nightModeItem = mock(MenuItem.class); - MenuItem hideArchivedItem = mock(MenuItem.class); - MenuItem hideCompletedItem = mock(MenuItem.class); - Menu androidMenu = mock(Menu.class); - when(androidMenu.findItem(R.id.actionToggleNightMode)).thenReturn( - nightModeItem); - when(androidMenu.findItem(R.id.actionHideArchived)).thenReturn( - hideArchivedItem); - when(androidMenu.findItem(R.id.actionHideCompleted)).thenReturn( - hideCompletedItem); - - when(preferences.getShowArchived()).thenReturn(false); - when(preferences.getShowCompleted()).thenReturn(false); - when(themeSwitcher.isNightMode()).thenReturn(false); - - menu.onCreate(androidMenu); - - verify(nightModeItem).setChecked(false); - verify(hideArchivedItem).setChecked(true); - verify(hideCompletedItem).setChecked(true); - reset(nightModeItem, hideArchivedItem, hideCompletedItem); - - when(preferences.getShowArchived()).thenReturn(true); - when(preferences.getShowCompleted()).thenReturn(true); - when(themeSwitcher.isNightMode()).thenReturn(true); - - menu.onCreate(androidMenu); - - verify(nightModeItem).setChecked(true); - verify(hideArchivedItem).setChecked(false); - verify(hideCompletedItem).setChecked(false); - } - - @Test - public void testOnSelected_about() - { - onItemSelected(R.id.actionAbout); - verify(behavior).onViewAbout(); - } - - @Test - public void testOnSelected_add() - { - onItemSelected(R.id.actionAdd); - verify(behavior).onCreateHabit(); - } - - @Test - public void testOnSelected_faq() - { - onItemSelected(R.id.actionFAQ); - verify(behavior).onViewFAQ(); - } - - @Test - public void testOnSelected_nightMode() - { - onItemSelected(R.id.actionToggleNightMode); - verify(behavior).onToggleNightMode(); - } - - @Test - public void testOnSelected_settings() - { - onItemSelected(R.id.actionSettings); - verify(behavior).onViewSettings(); - } - - @Test - public void testOnSelected_showArchived() - { - onItemSelected(R.id.actionHideArchived); - verify(behavior).onToggleShowArchived(); - } - - @Test - public void testOnSelected_showCompleted() - { - onItemSelected(R.id.actionHideCompleted); - verify(behavior).onToggleShowCompleted(); - } - - protected void onItemSelected(int actionId) - { - MenuItem item = mock(MenuItem.class); - when(item.getItemId()).thenReturn(actionId); - menu.onItemSelected(item); - } -} \ No newline at end of file diff --git a/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenuTest.kt b/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenuTest.kt new file mode 100644 index 000000000..09a6fdd94 --- /dev/null +++ b/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenuTest.kt @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2017 Á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.list + +import android.view.* +import org.isoron.androidbase.activities.* +import org.isoron.uhabits.* +import org.isoron.uhabits.core.preferences.* +import org.isoron.uhabits.core.ui.* +import org.isoron.uhabits.core.ui.screens.habits.list.* +import org.junit.* +import org.mockito.* +import org.mockito.Mockito.* + +class ListHabitsMenuTest : BaseAndroidJVMTest() { + @Mock lateinit var activity: BaseActivity + @Mock lateinit var preferences: Preferences + @Mock lateinit var themeSwitcher: ThemeSwitcher + @Mock lateinit var behavior: ListHabitsMenuBehavior + lateinit var menu: ListHabitsMenu + + @Before + override fun setUp() { + super.setUp() + menu = ListHabitsMenu(activity, preferences, + themeSwitcher, behavior) + } + + @Test + fun testOnCreate() { + val nightModeItem = mock(MenuItem::class.java) + val hideArchivedItem = mock(MenuItem::class.java) + val hideCompletedItem = mock(MenuItem::class.java) + val androidMenu = mock(Menu::class.java) + `when`(androidMenu.findItem(R.id.actionToggleNightMode)).thenReturn( + nightModeItem) + `when`(androidMenu.findItem(R.id.actionHideArchived)).thenReturn( + hideArchivedItem) + `when`(androidMenu.findItem(R.id.actionHideCompleted)).thenReturn( + hideCompletedItem) + + `when`(preferences.showArchived).thenReturn(false) + `when`(preferences.showCompleted).thenReturn(false) + `when`(themeSwitcher.isNightMode).thenReturn(false) + + menu.onCreate(androidMenu) + + verify(nightModeItem).isChecked = false + verify(hideArchivedItem).isChecked = true + verify(hideCompletedItem).isChecked = true + reset(nightModeItem, hideArchivedItem, hideCompletedItem) + + `when`(preferences.showArchived).thenReturn(true) + `when`(preferences.showCompleted).thenReturn(true) + `when`(themeSwitcher.isNightMode).thenReturn(true) + + menu.onCreate(androidMenu) + + verify(nightModeItem).isChecked = true + verify(hideArchivedItem).isChecked = false + verify(hideCompletedItem).isChecked = false + } + + @Test + fun testOnSelected_about() { + onItemSelected(R.id.actionAbout) + verify(behavior).onViewAbout() + } + + @Test + fun testOnSelected_add() { + onItemSelected(R.id.actionAdd) + verify(behavior).onCreateHabit() + } + + @Test + fun testOnSelected_faq() { + onItemSelected(R.id.actionFAQ) + verify(behavior).onViewFAQ() + } + + @Test + fun testOnSelected_nightMode() { + onItemSelected(R.id.actionToggleNightMode) + verify(behavior).onToggleNightMode() + } + + @Test + fun testOnSelected_settings() { + onItemSelected(R.id.actionSettings) + verify(behavior).onViewSettings() + } + + @Test + fun testOnSelected_showArchived() { + onItemSelected(R.id.actionHideArchived) + verify(behavior).onToggleShowArchived() + } + + @Test + fun testOnSelected_showCompleted() { + onItemSelected(R.id.actionHideCompleted) + verify(behavior).onToggleShowCompleted() + } + + private fun onItemSelected(actionId: Int) { + val item = mock(MenuItem::class.java) + `when`(item.itemId).thenReturn(actionId) + menu.onItemSelected(item) + } +} \ No newline at end of file diff --git a/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreenTest.java b/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreenTest.java deleted file mode 100644 index d72382f69..000000000 --- a/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreenTest.java +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright (C) 2017 Á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.list; - - -import android.content.*; - -import org.isoron.androidbase.activities.*; -import org.isoron.uhabits.R; -import org.isoron.uhabits.activities.common.dialogs.*; -import org.isoron.uhabits.activities.habits.edit.*; -import org.isoron.uhabits.core.commands.*; -import org.isoron.uhabits.core.models.*; -import org.isoron.uhabits.core.preferences.*; -import org.isoron.uhabits.core.ui.*; -import org.isoron.uhabits.core.ui.callbacks.*; -import org.isoron.uhabits.intents.*; -import org.junit.*; -import org.junit.runner.*; -import org.mockito.junit.*; - -import java.util.*; - -import static org.isoron.uhabits.activities.habits.list.ListHabitsScreen.*; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.*; -import static org.mockito.Mockito.eq; - -@RunWith(MockitoJUnitRunner.class) -public class ListHabitsScreenTest -{ - private BaseActivity activity; - - private ListHabitsRootView rootView; - - private ListHabitsScreen screen; - - private ListHabitsController controller; - - private Habit habit; - - private Intent intent; - - private ConfirmDeleteDialogFactory confirmDeleteDialogFactory; - - private IntentFactory intentFactory; - - private CommandRunner commandRunner; - - private ColorPickerDialogFactory colorPickerDialogFactory; - - private EditHabitDialogFactory dialogFactory; - - private ThemeSwitcher themeSwitcher; - - private Preferences prefs; - - private CommandParser commandParser; - - @Before - public void setUp() - { - activity = mock(ListHabitsActivity.class); - commandRunner = mock(CommandRunner.class); - rootView = mock(ListHabitsRootView.class); - intentFactory = mock(IntentFactory.class); - themeSwitcher = mock(ThemeSwitcher.class); - confirmDeleteDialogFactory = mock(ConfirmDeleteDialogFactory.class); - colorPickerDialogFactory = mock(ColorPickerDialogFactory.class); - dialogFactory = mock(EditHabitDialogFactory.class); - prefs = mock(Preferences.class); - commandParser = mock(CommandParser.class); - - screen = spy(new ListHabitsScreen(activity, commandRunner, rootView, - intentFactory, themeSwitcher, confirmDeleteDialogFactory, - colorPickerDialogFactory, dialogFactory, prefs)); - - doNothing().when(screen).showMessage(anyInt()); - - controller = mock(ListHabitsController.class); - screen.setController(controller); - - habit = mock(Habit.class); - intent = mock(Intent.class); - } - -// @Test -// public void testCreateHabitScreen() -// { -// CreateBooleanHabitDialog dialog = mock(CreateBooleanHabitDialog.class); -// when(createHabitDialogFactory.create()).thenReturn(dialog); -// -// screen.showCreateHabitScreen(); -// -// verify(activity).showDialog(eq(dialog), any()); -// } - - @Test - public void testOnAttached() - { - screen.onAttached(); - verify(commandRunner).addListener(screen); - } - - @Test - public void testOnCommand() - { - Command c = mock(DeleteHabitsCommand.class); - screen.onCommandExecuted(c, null); - verify(screen).showMessage(R.string.toast_habit_deleted); - } - - @Test - public void testOnDetach() - { - screen.onDettached(); - verify(commandRunner).removeListener(screen); - } - - @Test - public void testOnResult_bugReport() - { - screen.onResult(REQUEST_SETTINGS, RESULT_BUG_REPORT, null); - verify(controller).onSendBugReport(); - } - - @Test - public void testOnResult_exportCSV() - { - screen.onResult(REQUEST_SETTINGS, RESULT_EXPORT_CSV, null); - verify(controller).onExportCSV(); - } - - @Test - public void testOnResult_exportDB() - { - screen.onResult(REQUEST_SETTINGS, RESULT_EXPORT_DB, null); - verify(controller).onExportDB(); - } - - @Test - public void testOnResult_importData() - { - screen.onResult(REQUEST_SETTINGS, RESULT_IMPORT_DATA, null); - testShowImportScreen(); - } - - @Test - public void testShowAboutScreen() throws Exception - { - when(intentFactory.startAboutActivity(activity)).thenReturn(intent); - screen.showAboutScreen(); - verify(activity).startActivity(eq(intent)); - } - - @Test - public void testShowColorPicker() - { - ColorPickerDialog picker = mock(ColorPickerDialog.class); - when(colorPickerDialogFactory.create(999)).thenReturn(picker); - OnColorPickedCallback callback = mock(OnColorPickedCallback.class); - - screen.showColorPicker(999, callback); - - verify(activity).showDialog(eq(picker), any()); - verify(picker).setListener(callback); - } - - @Test - public void testShowDeleteConfirmationScreen() - { - OnConfirmedCallback callback = mock(OnConfirmedCallback.class); - ConfirmDeleteDialog dialog = mock(ConfirmDeleteDialog.class); - when(confirmDeleteDialogFactory.create(callback)).thenReturn(dialog); - - screen.showDeleteConfirmationScreen(callback); - - verify(activity).showDialog(dialog); - } - - @Test - public void testShowEditHabitScreen() - { - EditHabitDialog dialog = mock(EditHabitDialog.class); - when(dialogFactory.edit(habit)).thenReturn(dialog); - screen.showEditHabitsScreen(Collections.singletonList(habit)); - verify(activity).showDialog(eq(dialog), any()); - } - - @Test - public void testShowFAQScreen() - { - when(intentFactory.viewFAQ(activity)).thenReturn(intent); - screen.showFAQScreen(); - verify(activity).startActivity(intent); - } - - @Test - public void testShowHabitScreen() - { - when(intentFactory.startShowHabitActivity(activity, habit)).thenReturn( - intent); - screen.showHabitScreen(habit); - verify(activity).startActivity(intent); - } - - @Test - public void testShowImportScreen() - { - when(intentFactory.openDocument()).thenReturn(intent); - screen.showImportScreen(); - verify(activity).startActivityForResult(intent, REQUEST_OPEN_DOCUMENT); - } - - @Test - public void testShowIntroScreen() - { - when(intentFactory.startIntroActivity(activity)).thenReturn(intent); - screen.showIntroScreen(); - verify(activity).startActivity(intent); - } - - @Test - public void testShowSettingsScreen() - { - when(intentFactory.startSettingsActivity(activity)).thenReturn(intent); - screen.showSettingsScreen(); - verify(activity).startActivityForResult(eq(intent), anyInt()); - } - - @Test - public void testApplyTheme() - { - screen.applyTheme(); - verify(activity).restartWithFade(ListHabitsActivity.class); - } -} \ No newline at end of file diff --git a/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreenTest.kt b/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreenTest.kt new file mode 100644 index 000000000..ea206264f --- /dev/null +++ b/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreenTest.kt @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2017 Á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.list + +import android.content.* +import dagger.* +import org.isoron.androidbase.activities.* +import org.isoron.uhabits.* +import org.isoron.uhabits.activities.common.dialogs.* +import org.isoron.uhabits.activities.habits.edit.* +import org.isoron.uhabits.activities.habits.list.views.* +import org.isoron.uhabits.core.commands.* +import org.isoron.uhabits.core.models.* +import org.isoron.uhabits.core.preferences.* +import org.isoron.uhabits.core.ui.* +import org.isoron.uhabits.core.ui.callbacks.* +import org.isoron.uhabits.core.ui.screens.habits.list.* +import org.isoron.uhabits.intents.* +import org.isoron.uhabits.tasks.* +import org.junit.* +import org.junit.runner.* +import org.mockito.* +import org.mockito.ArgumentMatchers.* +import org.mockito.Mockito.`when` +import org.mockito.Mockito.doNothing +import org.mockito.Mockito.mock +import org.mockito.Mockito.spy +import org.mockito.Mockito.verify +import org.mockito.junit.* + +@RunWith(MockitoJUnitRunner::class) +class ListHabitsScreenTest : BaseAndroidJVMTest() { + @Mock lateinit var activity: BaseActivity + @Mock lateinit var habit: Habit + @Mock lateinit var intent: Intent + @Mock lateinit var rootView: ListHabitsRootView + @Mock lateinit var confirmDeleteDialogFactory: ConfirmDeleteDialogFactory + @Mock lateinit var intentFactory: IntentFactory + @Mock lateinit var colorPickerDialogFactory: ColorPickerDialogFactory + @Mock lateinit var editHabitDialogFactory: EditHabitDialogFactory + @Mock lateinit var themeSwitcher: ThemeSwitcher + @Mock lateinit var prefs: Preferences + @Mock lateinit var menu: ListHabitsMenu + @Mock lateinit var selectionMenu: ListHabitsSelectionMenu + @Mock lateinit var adapter: HabitCardListAdapter + @Mock lateinit var behavior: ListHabitsBehavior + @Mock lateinit var exportDBFactory: ExportDBTaskFactory + @Mock lateinit var importTaskFactory: ImportDataTaskFactory + @Mock lateinit var numberPickerFactory: NumberPickerFactory + + lateinit var screen: ListHabitsScreen + + @Before + override fun setUp() { + super.setUp() + commandRunner = mock(CommandRunner::class.java) + screen = spy(ListHabitsScreen( + activity = activity, + rootView = rootView, + commandRunner = commandRunner, + intentFactory = intentFactory, + themeSwitcher = themeSwitcher, + preferences = prefs, + confirmDeleteDialogFactory = confirmDeleteDialogFactory, + colorPickerFactory = colorPickerDialogFactory, + editHabitDialogFactory = editHabitDialogFactory, + menu = Lazy { menu }, + selectionMenu = Lazy { selectionMenu }, + adapter = adapter, + behavior = Lazy { behavior }, + taskRunner = taskRunner, + exportDBFactory = exportDBFactory, + importTaskFactory = importTaskFactory, + numberPickerFactory = numberPickerFactory)) + + doNothing().`when`(screen).showMessage(anyInt()) + } + + @Test + fun testApplyTheme() { + screen.applyTheme() + verify(activity).restartWithFade(ListHabitsActivity::class.java) + } + + @Test + fun testOnAttached() { + screen.onAttached() + verify(commandRunner).addListener(screen) + } + + @Test + fun testOnCommand() { + val c = mock(DeleteHabitsCommand::class.java) + screen.onCommandExecuted(c, null) + verify(screen).showMessage(R.string.toast_habit_deleted) + } + + @Test + fun testOnDetach() { + screen.onDettached() + verify(commandRunner).removeListener(screen) + } + + @Test + fun testOnResult_bugReport() { + screen.onResult(REQUEST_SETTINGS, RESULT_BUG_REPORT, null) + verify(behavior).onSendBugReport() + } + + @Test + fun testOnResult_exportCSV() { + screen.onResult(REQUEST_SETTINGS, RESULT_EXPORT_CSV, null) + verify(behavior).onExportCSV() + } + + @Test + fun testOnResult_importData() { + screen.onResult(REQUEST_SETTINGS, RESULT_IMPORT_DATA, null) + testShowImportScreen() + } + + @Test + @Throws(Exception::class) + fun testShowAboutScreen() { + `when`(intentFactory.startAboutActivity(activity)).thenReturn(intent) + screen.showAboutScreen() + verify(activity).startActivity(eq(intent)) + } + + @Test + fun testShowColorPicker() { + val picker = mock(ColorPickerDialog::class.java) + `when`(colorPickerDialogFactory.create(999)).thenReturn(picker) + val callback = mock(OnColorPickedCallback::class.java) + + screen.showColorPicker(999, callback) + + verify(activity).showDialog(eq(picker), any()) + verify(picker).setListener(callback) + } + + @Test + fun testShowDeleteConfirmationScreen() { + val callback = mock(OnConfirmedCallback::class.java) + val dialog = mock(ConfirmDeleteDialog::class.java) + `when`(confirmDeleteDialogFactory.create(callback)).thenReturn(dialog) + + screen.showDeleteConfirmationScreen(callback) + + verify(activity).showDialog(dialog) + } + + @Test + fun testShowEditHabitScreen() { + val dialog = mock(EditHabitDialog::class.java) + `when`(editHabitDialogFactory.edit(habit)).thenReturn(dialog) + screen.showEditHabitsScreen(listOf(habit)) + verify(activity).showDialog(eq(dialog), any()) + } + + @Test + fun testShowFAQScreen() { + `when`(intentFactory.viewFAQ(activity)).thenReturn(intent) + screen.showFAQScreen() + verify(activity).startActivity(intent) + } + + @Test + fun testShowHabitScreen() { + `when`(intentFactory.startShowHabitActivity(activity, habit)) + .thenReturn(intent) + screen.showHabitScreen(habit) + verify(activity).startActivity(intent) + } + + @Test + fun testShowImportScreen() { + `when`(intentFactory.openDocument()).thenReturn(intent) + screen.showImportScreen() + verify(activity).startActivityForResult(intent, REQUEST_OPEN_DOCUMENT) + } + + @Test + fun testShowIntroScreen() { + `when`(intentFactory.startIntroActivity(activity)).thenReturn(intent) + screen.showIntroScreen() + verify(activity).startActivity(intent) + } + + @Test + fun testShowSettingsScreen() { + `when`(intentFactory.startSettingsActivity(activity)).thenReturn(intent) + screen.showSettingsScreen() + verify(activity).startActivityForResult(eq(intent), anyInt()) + } +} \ No newline at end of file diff --git a/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/controllers/HabitCardListControllerTest.java b/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/controllers/HabitCardListControllerTest.java deleted file mode 100644 index b56e138c1..000000000 --- a/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/controllers/HabitCardListControllerTest.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2017 Á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.list.controllers; - -import org.isoron.uhabits.*; -import org.isoron.uhabits.core.models.*; -import org.isoron.uhabits.activities.habits.list.views.*; -import org.junit.*; - -import java.util.*; - -import static org.mockito.Mockito.*; - -public class HabitCardListControllerTest extends BaseAndroidUnitTest -{ - - private LinkedList habits; - - private HabitCardListView view; - - private HabitCardListAdapter adapter; - - private HabitCardListController controller; - - private HabitCardListController.HabitListener habitListener; - - private HabitCardListController.SelectionListener selectionListener; - - @Override - @Before - public void setUp() - { - super.setUp(); - - this.view = mock(HabitCardListView.class); - this.adapter = mock(HabitCardListAdapter.class); - this.habitListener = mock(HabitCardListController.HabitListener.class); - this.selectionListener = - mock(HabitCardListController.SelectionListener.class); - - habits = new LinkedList<>(); - for (int i = 0; i < 10; i++) - { - Habit mock = mock(Habit.class); - habits.add(mock); - - } - - resetMocks(); - - when(adapter.getObservable()).thenReturn(new ModelObservable()); - this.controller = new HabitCardListController(adapter); - controller.setHabitListener(habitListener); - controller.setSelectionListener(selectionListener); - view.setController(controller); - } - - @Test - public void testClick_withSelection() - { - controller.onItemLongClick(0); - verify(adapter).toggleSelection(0); - verify(selectionListener).onSelectionStart(); - resetMocks(); - - controller.onItemClick(1); - verify(adapter).toggleSelection(1); - verify(selectionListener).onSelectionChange(); - resetMocks(); - - controller.onItemClick(1); - verify(adapter).toggleSelection(1); - verify(selectionListener).onSelectionChange(); - resetMocks(); - - doReturn(true).when(adapter).isSelectionEmpty(); - controller.onItemClick(0); - verify(adapter).toggleSelection(0); - verify(selectionListener).onSelectionFinish(); - } - - @Test - public void testClick_withoutSelection() - { - controller.onItemClick(0); - verify(habitListener).onHabitClick(habits.get(0)); - } - - @Test - public void testDragAndDrop_withSelection() - { - controller.onItemLongClick(0); - verify(adapter).toggleSelection(0); - verify(selectionListener).onSelectionStart(); - resetMocks(); - - controller.startDrag(1); - verify(selectionListener).onSelectionChange(); - verify(adapter).toggleSelection(1); - resetMocks(); - - controller.drop(1, 3); - verify(habitListener).onHabitReorder(habits.get(1), habits.get(3)); - verify(selectionListener).onSelectionFinish(); - verify(adapter).performReorder(1, 3); - resetMocks(); - } - - @Test - public void testDragAndDrop_withoutSelection_distinctPlace() - { - controller.startDrag(0); - verify(selectionListener).onSelectionStart(); - verify(adapter).toggleSelection(0); - resetMocks(); - - controller.drop(0, 3); - verify(habitListener).onHabitReorder(habits.get(0), habits.get(3)); - verify(selectionListener).onSelectionFinish(); - verify(adapter).performReorder(0, 3); - verify(adapter).clearSelection(); - } - - @Test - public void testInvalidToggle() - { - controller.onInvalidToggle(); - verify(habitListener).onInvalidToggle(); - } - - @Test - public void testLongClick_withSelection() - { - controller.onItemLongClick(0); - verify(adapter).toggleSelection(0); - verify(selectionListener).onSelectionStart(); - resetMocks(); - - controller.onItemLongClick(1); - verify(adapter).toggleSelection(1); - verify(selectionListener).onSelectionChange(); - } - - @Test - public void testToggle() - { - controller.onToggle(habits.getFirst(), 0); - verify(habitListener).onToggle(habits.getFirst(), 0); - } - - protected void resetMocks() - { - reset(adapter, habitListener, selectionListener); - for (int i = 0; i < habits.size(); i++) - doReturn(habits.get(i)).when(adapter).getItem(i); - } -} \ No newline at end of file diff --git a/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/controllers/HabitCardListControllerTest.kt b/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/controllers/HabitCardListControllerTest.kt new file mode 100644 index 000000000..4dec267d0 --- /dev/null +++ b/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/controllers/HabitCardListControllerTest.kt @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2017 Á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.list.controllers + +import dagger.* +import org.isoron.uhabits.* +import org.isoron.uhabits.activities.habits.list.* +import org.isoron.uhabits.activities.habits.list.views.* +import org.isoron.uhabits.core.models.* +import org.isoron.uhabits.core.ui.screens.habits.list.* +import org.junit.* +import org.mockito.* +import org.mockito.Mockito.* +import java.util.* + +class HabitCardListControllerTest : BaseAndroidJVMTest() { + private val habits = LinkedList() + private lateinit var controller: HabitCardListController + + @Mock lateinit var adapter: HabitCardListAdapter + @Mock lateinit var behavior: ListHabitsBehavior + @Mock lateinit var selectionMenu: ListHabitsSelectionMenu + + @Before + override fun setUp() { + super.setUp() + `when`(adapter.observable).thenReturn(ModelObservable()) + controller = HabitCardListController(adapter, + behavior, + Lazy { selectionMenu }) + + repeat(10) { habits.add(fixtures.createEmptyHabit()) } + for(i in 0..9) `when`(adapter.getItem(i)).thenReturn(habits[i]) + + } + + @Test + fun testClick_withSelection() { + controller.onItemLongClick(0) + verify(adapter).toggleSelection(0) + verify(selectionMenu).onSelectionStart() + reset(adapter, selectionMenu) + + controller.onItemClick(1) + verify(adapter).toggleSelection(1) + verify(selectionMenu).onSelectionChange() + reset(adapter, selectionMenu) + + controller.onItemClick(1) + verify(adapter).toggleSelection(1) + verify(selectionMenu).onSelectionChange() + reset(adapter, selectionMenu) + + doReturn(true).`when`(adapter).isSelectionEmpty + controller.onItemClick(0) + verify(adapter).toggleSelection(0) + verify(selectionMenu).onSelectionFinish() + } + + @Test + fun testClick_withoutSelection() { + controller.onItemClick(0) + verify(behavior).onClickHabit(habits[0]) + } + + @Test + fun testDragAndDrop_withSelection() { + controller.onItemLongClick(0) + verify(adapter).toggleSelection(0) + verify(selectionMenu).onSelectionStart() + + controller.startDrag(1) + verify(selectionMenu).onSelectionChange() + verify(adapter).toggleSelection(1) + + controller.drop(1, 3) + verify(behavior).onReorderHabit(habits[1], habits[3]) + verify(selectionMenu).onSelectionFinish() + verify(adapter).performReorder(1, 3) + } + + @Test + fun testDragAndDrop_withoutSelection_distinctPlace() { + controller.startDrag(0) + verify(selectionMenu).onSelectionStart() + verify(adapter).toggleSelection(0) + + controller.drop(0, 3) + verify(behavior).onReorderHabit(habits[0], habits[3]) + verify(selectionMenu).onSelectionFinish() + verify(adapter).performReorder(0, 3) + verify(adapter).clearSelection() + } + + @Test + fun testLongClick_withSelection() { + controller.onItemLongClick(0) + verify(adapter).toggleSelection(0) + verify(selectionMenu).onSelectionStart() + + controller.onItemLongClick(1) + verify(adapter).toggleSelection(1) + verify(selectionMenu).onSelectionChange() + } +} \ No newline at end of file diff --git a/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/controllers/package-info.java b/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/controllers/package-info.java deleted file mode 100644 index 90ef83893..000000000 --- a/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/controllers/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 . - */ - -/** - * Contains views for ListHabitsActivity - */ -package org.isoron.uhabits.activities.habits.list.controllers; \ No newline at end of file diff --git a/uhabits-android/src/test/java/org/isoron/uhabits/receivers/ReminderControllerTest.java b/uhabits-android/src/test/java/org/isoron/uhabits/receivers/ReminderControllerTest.java index cbd161b8e..50b7711d6 100644 --- a/uhabits-android/src/test/java/org/isoron/uhabits/receivers/ReminderControllerTest.java +++ b/uhabits-android/src/test/java/org/isoron/uhabits/receivers/ReminderControllerTest.java @@ -29,7 +29,7 @@ import static org.mockito.Mockito.*; -public class ReminderControllerTest extends BaseAndroidUnitTest +public class ReminderControllerTest extends BaseAndroidJVMTest { private ReminderController controller; diff --git a/uhabits-android/src/test/java/org/isoron/uhabits/receivers/WidgetControllerTest.java b/uhabits-android/src/test/java/org/isoron/uhabits/receivers/WidgetControllerTest.java index 8a3966b57..73364c80f 100644 --- a/uhabits-android/src/test/java/org/isoron/uhabits/receivers/WidgetControllerTest.java +++ b/uhabits-android/src/test/java/org/isoron/uhabits/receivers/WidgetControllerTest.java @@ -32,7 +32,7 @@ import static org.isoron.uhabits.core.models.Checkmark.*; import static org.mockito.Mockito.*; -public class WidgetControllerTest extends BaseAndroidUnitTest +public class WidgetControllerTest extends BaseAndroidJVMTest { private WidgetBehavior controller; diff --git a/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/records/package-info.java b/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/records/package-info.java deleted file mode 100644 index 74a9ac796..000000000 --- a/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/records/package-info.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2017 Á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 . - * - * - */ - -/** - * Provides classes that represent rows in the SQLite database. - */ -package org.isoron.uhabits.core.models.sqlite.records; \ No newline at end of file diff --git a/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/Preferences.java b/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/Preferences.java index cd1d140c4..50985bdd4 100644 --- a/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/Preferences.java +++ b/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/Preferences.java @@ -212,6 +212,11 @@ public boolean isShortToggleEnabled() return storage.getBoolean("pref_short_toggle", false); } + public void setShortToggleEnabled(boolean enabled) + { + storage.putBoolean("pref_short_toggle", enabled); + } + public boolean isSyncEnabled() { return storage.getBoolean("pref_feature_sync", false); @@ -243,11 +248,11 @@ public void setNotificationsSticky(boolean sticky) for (Listener l : listeners) l.onNotificationsChanged(); } - public void setShouldReverseCheckmarks(boolean reverse) + public void setCheckmarkSequenceReversed(boolean reverse) { shouldReverseCheckmarks = reverse; storage.putBoolean("pref_checkmark_reverse_order", reverse); - for (Listener l : listeners) l.onCheckmarkOrderChanged(); + for (Listener l : listeners) l.onCheckmarkSequenceChanged(); } public void setSyncEnabled(boolean isEnabled) @@ -261,7 +266,7 @@ public boolean shouldMakeNotificationsSticky() return storage.getBoolean("pref_sticky_notifications", false); } - public boolean shouldReverseCheckmarks() + public boolean isCheckmarkSequenceReversed() { if (shouldReverseCheckmarks == null) shouldReverseCheckmarks = storage.getBoolean("pref_checkmark_reverse_order", false); @@ -277,7 +282,7 @@ public void updateLastHint(int number, long timestamp) public interface Listener { - default void onCheckmarkOrderChanged() {} + default void onCheckmarkSequenceChanged() {} default void onNotificationsChanged() {} diff --git a/uhabits-core/src/main/java/org/isoron/uhabits/core/tasks/SingleThreadTaskRunner.java b/uhabits-core/src/main/java/org/isoron/uhabits/core/tasks/SingleThreadTaskRunner.java index 748b8521d..f01257839 100644 --- a/uhabits-core/src/main/java/org/isoron/uhabits/core/tasks/SingleThreadTaskRunner.java +++ b/uhabits-core/src/main/java/org/isoron/uhabits/core/tasks/SingleThreadTaskRunner.java @@ -19,21 +19,27 @@ package org.isoron.uhabits.core.tasks; +import java.util.*; + public class SingleThreadTaskRunner implements TaskRunner { + private List listeners = new LinkedList<>(); + @Override public void addListener(Listener listener) { - throw new UnsupportedOperationException(); + listeners.add(listener); } @Override public void execute(Task task) { + for(Listener l : listeners) l.onTaskStarted(task); task.onAttached(this); task.onPreExecute(); task.doInBackground(); task.onPostExecute(); + for(Listener l : listeners) l.onTaskFinished(task); } @Override @@ -51,6 +57,6 @@ public void publishProgress(Task task, int progress) @Override public void removeListener(Listener listener) { - throw new UnsupportedOperationException(); + listeners.remove(listener); } } diff --git a/uhabits-core/src/test/java/org/isoron/uhabits/core/models/sqlite/SQLiteHabitListTest.java b/uhabits-core/src/test/java/org/isoron/uhabits/core/models/sqlite/SQLiteHabitListTest.java index a1d79372d..0c7ba02f2 100644 --- a/uhabits-core/src/test/java/org/isoron/uhabits/core/models/sqlite/SQLiteHabitListTest.java +++ b/uhabits-core/src/test/java/org/isoron/uhabits/core/models/sqlite/SQLiteHabitListTest.java @@ -15,8 +15,6 @@ * * You should have received a copy of the GNU General Public License along * with this program. If not, see . - * - * */ package org.isoron.uhabits.core.models.sqlite;

)b}CRPZYg6D z*s0@kyU>?b#R4NFn}x5`6CUH42=-o19+-MVH#w~^127Rz^x;(5$@-M>r+?vWOV)Gp z(93i8j+J8HHSqI!%gf7seDN!Lwq>{%lXl4KzsTFjVUU9(`Bc-vl+c1n89Qj*79*Og z-ac|nK1u+_E&y;B98D9beW%UAaB>hrl$zu=8ds)Ld^2UwCWd4ql(2)eWFOqHfJ<&_ ziVXp}rAPLbyC7qg@R+Cu9(A$j=WVM)>s+Y~{HxTx81id15xffKCX+-jq?b-mQr)}? z)SlUPzwe0%32q>>aOZM*Q*xF5@m!q6dIBcf+iP=6ZARLzPEq@g*785{4duhstE6mWXgj0;< zj9*MR_x#rtrTE~hjzNS3- zdq$McPSRbV7^M1s=Qy8TARWEiz-K`T&U>~g1JjTOuUa4#^++#0U46Tixhui?BI^F3 z>pfONpnN$$jD=5$GFIy*7?zo3<7|U)b^yrA#fu|u;hqsyU;PbEWB2`KR{|q^e0-!< z%7NzdJLhUS!YPh#rFM5y-8|#X70MaX)sTR+N#)MkKW0VeaLHbDRKGTc2Zk&P_$&qf zIKVmZ3B|Ksswm2>B#3QJ2RGiSKWG|GA`t`XLm1Vq%#XiswYwG)Qr=FplcX$^06by~ l$NqPe7exC%U6*6lL?;Ywe$ykErfmj>F4&!~w77ixzW|hxo3{V} diff --git a/uhabits-android/src/androidTest/assets/views-v21/habits/list/HeaderView/render_reverse.png b/uhabits-android/src/androidTest/assets/views-v21/habits/list/HeaderView/render_reverse.png index 09460ab18ae7b3fab8c016eeb28e9f2370d424ba..ca045595e6180be5d6f4fdc02935f861c4ab5561 100644 GIT binary patch literal 5287 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 Jt2lcl@joTdm>B>7 diff --git a/uhabits-android/src/androidTest/assets/views-v21/habits/list/NumberPanelView/render.png b/uhabits-android/src/androidTest/assets/views-v21/habits/list/NumberPanelView/render.png new file mode 100644 index 0000000000000000000000000000000000000000..9e9857e1834c5eceecd0fe7c6835e64af7330835 GIT binary patch literal 7590 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 J4|=W-{|E79rAPn( literal 0 HcmV?d00001 diff --git a/uhabits-android/src/androidTest/assets/views-v21/habits/list/NumberPanelView/render_different_color.png b/uhabits-android/src/androidTest/assets/views-v21/habits/list/NumberPanelView/render_different_color.png new file mode 100644 index 0000000000000000000000000000000000000000..165226baabccd88f53b0a2dd1cbee4abaee98a78 GIT binary patch literal 7524 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 F{{Z!5VK4vy literal 0 HcmV?d00001 diff --git a/uhabits-android/src/androidTest/assets/views-v21/habits/list/NumberPanelView/render_offset.png b/uhabits-android/src/androidTest/assets/views-v21/habits/list/NumberPanelView/render_offset.png new file mode 100644 index 0000000000000000000000000000000000000000..8460f9b4f2d343ac26026138f2bfd92aec106a36 GIT binary patch literal 8057 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�WyK0sOa`1prW>}F036>%ECL7VLwAP7e713*C4yM7z93X zYiP8X!k(LYqwPjX#3s3g<(g=zfVolq$7-RswZ5+3)fkQutoq585zHIOb58(wjnX_% zeDrx83BvioNt!MDgJ1=GD%edG;HP)6T0{R`P=s07`87@lBFVOD>-P4jMs>IT#xlm( zmR;)~ohxzgJackdmyJ-uGU+B9RG$XeiHSZLSp$xNHA8K{k*c_H)` zCcpTs3%yXK6wCo=9Co*MNvEYut9r8aoZxkrKH`q!&fAy(b~^RxOaAMdGj{~{^pq0u z+j-mjr$+(w;dWUAD+yK}-&Xc>c;K0;wfmmd|L4)``*Ad8<9r`ipg@lc)#{)mdSH@C zQ*C`+if5a&1MH-?O5Ah$(|3ASLHSY1qy}bx8PMXvPi`+5z7{JZ_r8r>=%N?A(2 zN+&^3OH#Bx#yDI!XDlgoT-2;hu&vgv7Rm+FkRr>AFr#Wm0j=cXH?Vo8rV?p~5?uuy z+sAppoDc9pbx9ZKL#a(As7CX)E$#YWGWUVo4b|Fv4om^}Qkq*pw46y7G`$ZlD-r`C zI0s<$z~AB3DnN~}6AVvnvD(&a!z*%Oqu@idHnQI;I+DrUsls`Hdmulc|3&!CS)O@> zQa&ZNmvX%6m|^RdEZuxvuqI|2l(kQLiOk_80D%U3L#sFpe3N5d6R`gW)o$}OYsnbM z0Ze!Z@5h*hKMmq&gB83;K=4wJx8SZ5wI-awrWG zK1phq(s1wHk6VpyWSJXR-D$lgs#|KdaAlNwNjP#*BUGEc90i1Def6dD3T1&S@<=Ck z)F~U^3|0#4FYtM|@P>~x7rIkT=}I0zivtycxq0C8uxIRAU@NJiuR39TW{d}7^XF%liHXTrCqMum^R_APJ%?r8gokmPXG=e)?|H%F zM`s1#5%rP8tR<;4rbUBiAWSU(`6CHBQcnj4zP#50XsoBb_bRM;Jnj(+WN+oI9iF?V>C{VH{g<5fBOF}17)xRGc}o@pden)`Knpvvrbrnfdj@c9!#llWn1ee-P}0n^-T$yl%8bU zoAaAx)D&Vc7+QG^$*uz22=V7j7Z+h(nFzagQ=3+P`N31QF1@ogPU8*05hy4g@iuMZ zDWDOH8o4THx>t)i9hYZ=vH&bV286R-P(KwV;EJ`1={-F?12>A(ofB8@eZCc~`Km)P zT<sUQ-TYcR%<0Ymi6M{h>H-xfZc~$hFv~?4N#8Veed7yyJt*0hqrUk(L1pYZ6r` zkhwXOWP5HZW(*ko1M@gszeYtpc#3`s-u3_TXgO8v);9^%e2_{2-=zbZs(Og>2R4!a E1MtD9AOHXW literal 0 HcmV?d00001 diff --git a/uhabits-android/src/androidTest/assets/views-v21/habits/list/NumberPanelView/render_reversed.png b/uhabits-android/src/androidTest/assets/views-v21/habits/list/NumberPanelView/render_reversed.png new file mode 100644 index 0000000000000000000000000000000000000000..2adf58c23f016ef8c462820a952e9337e16ddad9 GIT binary patch literal 7588 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 literal 0 HcmV?d00001 diff --git a/uhabits-android/src/androidTest/assets/views-v21/habits/show/FrequencyCard/render.png b/uhabits-android/src/androidTest/assets/views-v21/habits/show/FrequencyCard/render.png index 275a8d4892a83f2fb354a46f7c9c485b82fd6c58..bc3330fb4a2b2e0a46ed68876ad38a5bcd622d76 100644 GIT binary patch literal 24936 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 diff --git a/uhabits-android/src/androidTest/assets/views-v21/habits/show/SubtitleCard/render.png b/uhabits-android/src/androidTest/assets/views-v21/habits/show/SubtitleCard/render.png index 3b81389408ae22504e1d4af5f1bdf4c47b1b83c8..96e2310e030e4c70463c50e567e100dd7691e802 100644 GIT binary patch literal 15716 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