diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/ScoreChart.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/ScoreChart.java index d93e216ec..310307ee9 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/ScoreChart.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/ScoreChart.java @@ -125,7 +125,6 @@ public class ScoreChart extends ScrollableChart } } - @Deprecated public void setBucketSize(int bucketSize) { this.bucketSize = bucketSize; diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt index f3b395365..cf8fbc77b 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt @@ -31,11 +31,15 @@ import org.isoron.uhabits.core.models.* import org.isoron.uhabits.core.preferences.* import org.isoron.uhabits.databinding.* import org.isoron.uhabits.utils.* +import org.isoron.uhabits.widgets.* class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener { - private lateinit var view: ShowHabitView - private lateinit var presenter: ShowHabitPresenter private lateinit var commandRunner: CommandRunner + private lateinit var preferences: Preferences + private lateinit var presenter: ShowHabitPresenter + private lateinit var view: ShowHabitView + private lateinit var widgetUpdater: WidgetUpdater + private val scope = CoroutineScope(Dispatchers.Main) override fun onCreate(savedInstanceState: Bundle?) { @@ -43,7 +47,9 @@ class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener { val appComponent = (applicationContext as HabitsApplication).component val habitList = appComponent.habitList val habit = habitList.getById(ContentUris.parseId(intent.data!!))!! + preferences = appComponent.preferences commandRunner = appComponent.commandRunner + widgetUpdater = appComponent.widgetUpdater view = ShowHabitView(this) presenter = ShowHabitPresenter( @@ -51,6 +57,13 @@ class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener { context = this, preferences = appComponent.preferences ) + + view.onBucketSizeSelected = { position -> + preferences.defaultScoreSpinnerPosition = position + widgetUpdater.updateWidgets(habit.id) + updateViews() + } + setContentView(view) } @@ -85,13 +98,17 @@ data class ShowHabitViewModel( val notes: NotesCardViewModel, val target: TargetCardViewModel, val streaks: StreakCardViewModel, + val scores: ScoreCardViewModel, ) class ShowHabitView(context: Context) : FrameLayout(context) { private val binding = ShowHabitBinding.inflate(LayoutInflater.from(context)) + var onBucketSizeSelected: (position: Int) -> Unit = {} + init { addView(binding.root) + binding.scoreCard.onBucketSizeSelected = { position -> onBucketSizeSelected(position) } } fun update(data: ShowHabitViewModel) { @@ -101,6 +118,7 @@ class ShowHabitView(context: Context) : FrameLayout(context) { binding.notesCard.update(data.notes) binding.targetCard.update(data.target) binding.streakCard.update(data.streaks) + binding.scoreCard.update(data.scores) if (data.isNumerical) { binding.overviewCard.visibility = GONE binding.streakCard.visibility = GONE @@ -128,6 +146,8 @@ class ShowHabitPresenter( firstWeekday = preferences.firstWeekday, resources = context.resources) private val streakCartPresenter = StreakCartPresenter(habit) + private val scoreCardPresenter = ScoreCardPresenter(habit = habit, + firstWeekday = preferences.firstWeekday) suspend fun present(): ShowHabitViewModel { return ShowHabitViewModel( @@ -139,7 +159,7 @@ class ShowHabitPresenter( notes = notesCardPresenter.present(), target = targetCardPresenter.present(), streaks = streakCartPresenter.present(), + scores = scoreCardPresenter.present(preferences.defaultScoreSpinnerPosition) ) } - } \ No newline at end of file diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/BarCard.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/BarCard.java index b37ea11fd..a0bc7e59f 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/BarCard.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/BarCard.java @@ -37,8 +37,6 @@ import java.util.*; import butterknife.*; -import static org.isoron.uhabits.activities.habits.show.views.ScoreCard.getTruncateField; - public class BarCard extends HabitCard { public static final int[] NUMERICAL_BUCKET_SIZES = {1, 7, 31, 92, 365}; @@ -134,7 +132,7 @@ public class BarCard extends HabitCard int firstWeekday = Calendar.SATURDAY; if (prefs != null) firstWeekday = prefs.getFirstWeekday(); if (bucketSize == 1) checkmarks = habit.getCheckmarks().getAll(); - else checkmarks = habit.getCheckmarks().groupBy(getTruncateField(bucketSize), + else checkmarks = habit.getCheckmarks().groupBy(ScoreCardPresenter.Companion.getTruncateField(bucketSize), firstWeekday); chart.setCheckmarks(checkmarks); chart.setBucketSize(bucketSize); diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/ScoreCard.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/ScoreCard.java deleted file mode 100644 index 4eb5d5e69..000000000 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/ScoreCard.java +++ /dev/null @@ -1,168 +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.show.views; - -import android.content.*; -import android.util.*; -import android.widget.*; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import org.isoron.uhabits.*; -import org.isoron.uhabits.R; -import org.isoron.uhabits.activities.common.views.*; -import org.isoron.uhabits.core.models.*; -import org.isoron.uhabits.core.preferences.*; -import org.isoron.uhabits.core.tasks.*; -import org.isoron.uhabits.core.utils.*; -import org.isoron.uhabits.utils.*; - -import java.util.*; - -import butterknife.*; - -public class ScoreCard extends HabitCard -{ - public static final int[] BUCKET_SIZES = { 1, 7, 31, 92, 365 }; - - @BindView(R.id.spinner) - Spinner spinner; - - @BindView(R.id.scoreView) - ScoreChart chart; - - @BindView(R.id.title) - TextView title; - - private int bucketSize; - - @Nullable - private Preferences prefs; - - public ScoreCard(Context context) - { - super(context); - init(); - } - - public ScoreCard(Context context, AttributeSet attrs) - { - super(context, attrs); - init(); - } - - @NonNull - public static DateUtils.TruncateField getTruncateField(int bucketSize) - { - if (bucketSize == 7) return DateUtils.TruncateField.WEEK_NUMBER; - if (bucketSize == 31) return DateUtils.TruncateField.MONTH; - if (bucketSize == 92) return DateUtils.TruncateField.QUARTER; - if (bucketSize == 365) return DateUtils.TruncateField.YEAR; - - Log.e("ScoreCard", - String.format("Unknown bucket size: %d", bucketSize)); - - return DateUtils.TruncateField.MONTH; - } - - @OnItemSelected(R.id.spinner) - public void onItemSelected(int position) - { - setBucketSizeFromPosition(position); - HabitsApplication app = - (HabitsApplication) getContext().getApplicationContext(); - app.getComponent().getWidgetUpdater().updateWidgets(); - refreshData(); - } - - private int getDefaultSpinnerPosition() - { - if(prefs == null) return 0; - return prefs.getDefaultScoreSpinnerPosition(); - } - - private void init() - { - Context appContext = getContext().getApplicationContext(); - if (appContext instanceof HabitsApplication) - { - HabitsApplication app = (HabitsApplication) appContext; - prefs = app.getComponent().getPreferences(); - } - - inflate(getContext(), R.layout.show_habit_score, this); - ButterKnife.bind(this); - - int defaultPosition = getDefaultSpinnerPosition(); - setBucketSizeFromPosition(defaultPosition); - spinner.setSelection(defaultPosition); - - if (isInEditMode()) - { - spinner.setVisibility(GONE); - title.setTextColor(PaletteUtils.getAndroidTestColor(1)); - chart.setColor(PaletteUtils.getAndroidTestColor(1)); - chart.populateWithRandomData(); - } - } - - private void setBucketSizeFromPosition(int position) - { - if(prefs == null) return; - prefs.setDefaultScoreSpinnerPosition(position); - bucketSize = BUCKET_SIZES[position]; - } - - @Override - protected Task createRefreshTask() - { - return new RefreshTask(); - } - - private class RefreshTask extends CancelableTask - { - @Override - public void doInBackground() - { - if (isCanceled()) return; - List scores; - ScoreList scoreList = getHabit().getScores(); - int firstWeekday = Calendar.SATURDAY; - if (prefs != null) firstWeekday = prefs.getFirstWeekday(); - Log.d("ScoreCard", "firstWeekday="+firstWeekday); - - if (bucketSize == 1) scores = scoreList.toList(); - else scores = scoreList.groupBy(getTruncateField(bucketSize), firstWeekday); - - chart.setScores(scores); - chart.reset(); - chart.setBucketSize(bucketSize); - } - - @Override - public void onPreExecute() - { - int color = PaletteUtilsKt.toThemedAndroidColor(getHabit().getColor(), getContext()); - title.setTextColor(color); - chart.setColor(color); - } - } -} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/ScoreCard.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/ScoreCard.kt new file mode 100644 index 000000000..99256b565 --- /dev/null +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/ScoreCard.kt @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ +package org.isoron.uhabits.activities.habits.show.views + +import android.content.* +import android.util.* +import android.view.* +import android.widget.* +import org.isoron.uhabits.core.models.* +import org.isoron.uhabits.core.utils.* +import org.isoron.uhabits.core.utils.DateUtils.TruncateField.* +import org.isoron.uhabits.databinding.* +import org.isoron.uhabits.utils.* + +data class ScoreCardViewModel( + val scores: List, + val bucketSize: Int, + val spinnerPosition: Int, + val color: PaletteColor, +) + +class ScoreCard(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) { + private var binding = ShowHabitScoreBinding.inflate(LayoutInflater.from(context), this) + + var onBucketSizeSelected: (position: Int) -> Unit = {} + + fun update(data: ScoreCardViewModel) { + val androidColor = data.color.toThemedAndroidColor(context) + binding.title.setTextColor(androidColor) + binding.spinner.setSelection(data.spinnerPosition) + binding.scoreView.setScores(data.scores) + binding.scoreView.reset() + binding.scoreView.setBucketSize(data.bucketSize) + binding.scoreView.setColor(androidColor) + + binding.spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + onBucketSizeSelected(position) + } + override fun onNothingSelected(parent: AdapterView<*>?) { + } + } + } +} + +class ScoreCardPresenter( + val habit: Habit, + val firstWeekday: Int, +) { + companion object { + val BUCKET_SIZES = intArrayOf(1, 7, 31, 92, 365) + fun getTruncateField(bucketSize: Int): DateUtils.TruncateField { + when (bucketSize) { + 7 -> return WEEK_NUMBER + 31 -> return MONTH + 92 -> return QUARTER + 365 -> return YEAR + else -> return MONTH + } + } + } + + fun present(spinnerPosition: Int): ScoreCardViewModel { + val bucketSize = BUCKET_SIZES[spinnerPosition] + val scoreList = habit.scores + val scores = if (bucketSize == 1) scoreList.toList() + else scoreList.groupBy(getTruncateField(bucketSize), firstWeekday) + return ScoreCardViewModel( + color = habit.color, + scores = scores, + bucketSize = bucketSize, + spinnerPosition = spinnerPosition, + ) + } + +} \ No newline at end of file diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/ScoreWidget.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/ScoreWidget.kt index 88aaead6e..9f0f73aa8 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/ScoreWidget.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/ScoreWidget.kt @@ -37,11 +37,10 @@ class ScoreWidget( pendingIntentFactory.showHabit(habit) override fun refreshData(view: View) { - val size = ScoreCard.BUCKET_SIZES[prefs.defaultScoreSpinnerPosition] + val size = ScoreCardPresenter.BUCKET_SIZES[prefs.defaultScoreSpinnerPosition] val scores = when(size) { 1 -> habit.scores.toList() - else -> habit.scores.groupBy(ScoreCard.getTruncateField(size), - prefs.firstWeekday) + else -> habit.scores.groupBy(ScoreCardPresenter.getTruncateField(size), prefs.firstWeekday) } val widgetView = view as GraphWidgetView