mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 09:08:52 -06:00
Add dialog and notes indicator for HistoryChart
This commit is contained in:
@@ -49,23 +49,12 @@ class AndroidDataView(
|
|||||||
override fun onShowPress(e: MotionEvent?) = Unit
|
override fun onShowPress(e: MotionEvent?) = Unit
|
||||||
|
|
||||||
override fun onSingleTapUp(e: MotionEvent?): Boolean {
|
override fun onSingleTapUp(e: MotionEvent?): Boolean {
|
||||||
val x: Float
|
return handleClick(e, true)
|
||||||
val y: Float
|
|
||||||
try {
|
|
||||||
val pointerId = e!!.getPointerId(0)
|
|
||||||
x = e.getX(pointerId)
|
|
||||||
y = e.getY(pointerId)
|
|
||||||
} catch (ex: RuntimeException) {
|
|
||||||
// Android often throws IllegalArgumentException here. Apparently,
|
|
||||||
// the pointer id may become invalid shortly after calling
|
|
||||||
// e.getPointerId.
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
view?.onClick(x / canvas.innerDensity, y / canvas.innerDensity)
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLongPress(e: MotionEvent?) = Unit
|
override fun onLongPress(e: MotionEvent?) {
|
||||||
|
handleClick(e)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onScroll(
|
override fun onScroll(
|
||||||
e1: MotionEvent?,
|
e1: MotionEvent?,
|
||||||
@@ -137,4 +126,22 @@ class AndroidDataView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun handleClick(e: MotionEvent?, isSingleTap: Boolean = false): Boolean {
|
||||||
|
val x: Float
|
||||||
|
val y: Float
|
||||||
|
try {
|
||||||
|
val pointerId = e!!.getPointerId(0)
|
||||||
|
x = e.getX(pointerId)
|
||||||
|
y = e.getY(pointerId)
|
||||||
|
} catch (ex: RuntimeException) {
|
||||||
|
// Android often throws IllegalArgumentException here. Apparently,
|
||||||
|
// the pointer id may become invalid shortly after calling
|
||||||
|
// e.getPointerId.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (isSingleTap) view?.onClick(x / canvas.innerDensity, y / canvas.innerDensity)
|
||||||
|
else view?.onLongClick(x / canvas.innerDensity, y / canvas.innerDensity)
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,9 +63,10 @@ class HistoryEditorDialog : AppCompatDialogFragment(), CommandRunner.Listener {
|
|||||||
paletteColor = habit.color,
|
paletteColor = habit.color,
|
||||||
series = emptyList(),
|
series = emptyList(),
|
||||||
defaultSquare = HistoryChart.Square.OFF,
|
defaultSquare = HistoryChart.Square.OFF,
|
||||||
|
hasNotes = emptyList(),
|
||||||
theme = themeSwitcher.currentTheme,
|
theme = themeSwitcher.currentTheme,
|
||||||
today = DateUtils.getTodayWithOffset().toLocalDate(),
|
today = DateUtils.getTodayWithOffset().toLocalDate(),
|
||||||
onDateClickedListener = onDateClickedListener ?: OnDateClickedListener { },
|
onDateClickedListener = onDateClickedListener ?: OnDateClickedListener { _, _ -> },
|
||||||
padding = 10.0,
|
padding = 10.0,
|
||||||
)
|
)
|
||||||
dataView = AndroidDataView(context!!, null)
|
dataView = AndroidDataView(context!!, null)
|
||||||
@@ -103,6 +104,7 @@ class HistoryEditorDialog : AppCompatDialogFragment(), CommandRunner.Listener {
|
|||||||
)
|
)
|
||||||
chart?.series = model.series
|
chart?.series = model.series
|
||||||
chart?.defaultSquare = model.defaultSquare
|
chart?.defaultSquare = model.defaultSquare
|
||||||
|
chart?.hasNotes = model.hasNotes
|
||||||
dataView.postInvalidate()
|
dataView.postInvalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ class HistoryCardView(context: Context, attrs: AttributeSet) : LinearLayout(cont
|
|||||||
dateFormatter = JavaLocalDateFormatter(Locale.getDefault()),
|
dateFormatter = JavaLocalDateFormatter(Locale.getDefault()),
|
||||||
series = state.series,
|
series = state.series,
|
||||||
defaultSquare = state.defaultSquare,
|
defaultSquare = state.defaultSquare,
|
||||||
|
hasNotes = state.hasNotes,
|
||||||
firstWeekday = state.firstWeekday,
|
firstWeekday = state.firstWeekday,
|
||||||
)
|
)
|
||||||
binding.chart.postInvalidate()
|
binding.chart.postInvalidate()
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ class HistoryWidget(
|
|||||||
val historyChart = (this.view as HistoryChart)
|
val historyChart = (this.view as HistoryChart)
|
||||||
historyChart.series = model.series
|
historyChart.series = model.series
|
||||||
historyChart.defaultSquare = model.defaultSquare
|
historyChart.defaultSquare = model.defaultSquare
|
||||||
|
historyChart.hasNotes = model.hasNotes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,6 +75,7 @@ class HistoryWidget(
|
|||||||
firstWeekday = prefs.firstWeekday,
|
firstWeekday = prefs.firstWeekday,
|
||||||
series = listOf(),
|
series = listOf(),
|
||||||
defaultSquare = HistoryChart.Square.OFF,
|
defaultSquare = HistoryChart.Square.OFF,
|
||||||
|
hasNotes = listOf(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
).apply {
|
).apply {
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ interface View {
|
|||||||
fun draw(canvas: Canvas)
|
fun draw(canvas: Canvas)
|
||||||
fun onClick(x: Double, y: Double) {
|
fun onClick(x: Double, y: Double) {
|
||||||
}
|
}
|
||||||
|
fun onLongClick(x: Double, y: Double) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DataView : View {
|
interface DataView : View {
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ data class HistoryCardState(
|
|||||||
val firstWeekday: DayOfWeek,
|
val firstWeekday: DayOfWeek,
|
||||||
val series: List<HistoryChart.Square>,
|
val series: List<HistoryChart.Square>,
|
||||||
val defaultSquare: HistoryChart.Square,
|
val defaultSquare: HistoryChart.Square,
|
||||||
|
val hasNotes: List<Boolean>,
|
||||||
val theme: Theme,
|
val theme: Theme,
|
||||||
val today: LocalDate,
|
val today: LocalDate,
|
||||||
)
|
)
|
||||||
@@ -58,7 +59,7 @@ class HistoryCardPresenter(
|
|||||||
val screen: Screen,
|
val screen: Screen,
|
||||||
) : OnDateClickedListener {
|
) : OnDateClickedListener {
|
||||||
|
|
||||||
override fun onDateClicked(date: LocalDate) {
|
override fun onDateClicked(date: LocalDate, isLongClick: Boolean) {
|
||||||
val timestamp = Timestamp.fromLocalDate(date)
|
val timestamp = Timestamp.fromLocalDate(date)
|
||||||
screen.showFeedback()
|
screen.showFeedback()
|
||||||
if (habit.isNumerical) {
|
if (habit.isNumerical) {
|
||||||
@@ -81,20 +82,34 @@ class HistoryCardPresenter(
|
|||||||
val entry = habit.computedEntries.get(timestamp)
|
val entry = habit.computedEntries.get(timestamp)
|
||||||
val currentValue = entry.value
|
val currentValue = entry.value
|
||||||
val notes = entry.notes
|
val notes = entry.notes
|
||||||
val nextValue = Entry.nextToggleValue(
|
if (!isLongClick) {
|
||||||
value = currentValue,
|
val nextValue = Entry.nextToggleValue(
|
||||||
isSkipEnabled = preferences.isSkipEnabled,
|
value = currentValue,
|
||||||
areQuestionMarksEnabled = preferences.areQuestionMarksEnabled
|
isSkipEnabled = preferences.isSkipEnabled,
|
||||||
)
|
areQuestionMarksEnabled = preferences.areQuestionMarksEnabled
|
||||||
commandRunner.run(
|
)
|
||||||
CreateRepetitionCommand(
|
commandRunner.run(
|
||||||
habitList,
|
CreateRepetitionCommand(
|
||||||
habit,
|
habitList,
|
||||||
timestamp,
|
habit,
|
||||||
nextValue,
|
timestamp,
|
||||||
notes,
|
nextValue,
|
||||||
),
|
notes,
|
||||||
)
|
),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
screen.showCheckmarkDialog(notes) { newNotes ->
|
||||||
|
commandRunner.run(
|
||||||
|
CreateRepetitionCommand(
|
||||||
|
habitList,
|
||||||
|
habit,
|
||||||
|
timestamp,
|
||||||
|
currentValue,
|
||||||
|
newNotes,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,6 +157,13 @@ class HistoryCardPresenter(
|
|||||||
else
|
else
|
||||||
HistoryChart.Square.OFF
|
HistoryChart.Square.OFF
|
||||||
|
|
||||||
|
val hasNotes = entries.map {
|
||||||
|
when (it.notes) {
|
||||||
|
"" -> false
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return HistoryCardState(
|
return HistoryCardState(
|
||||||
color = habit.color,
|
color = habit.color,
|
||||||
firstWeekday = firstWeekday,
|
firstWeekday = firstWeekday,
|
||||||
@@ -149,6 +171,7 @@ class HistoryCardPresenter(
|
|||||||
theme = theme,
|
theme = theme,
|
||||||
series = series,
|
series = series,
|
||||||
defaultSquare = defaultSquare
|
defaultSquare = defaultSquare
|
||||||
|
hasNotes = hasNotes,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import kotlin.math.min
|
|||||||
import kotlin.math.round
|
import kotlin.math.round
|
||||||
|
|
||||||
fun interface OnDateClickedListener {
|
fun interface OnDateClickedListener {
|
||||||
fun onDateClicked(date: LocalDate)
|
fun onDateClicked(date: LocalDate, isLongClick: Boolean)
|
||||||
}
|
}
|
||||||
|
|
||||||
class HistoryChart(
|
class HistoryChart(
|
||||||
@@ -42,9 +42,10 @@ class HistoryChart(
|
|||||||
var paletteColor: PaletteColor,
|
var paletteColor: PaletteColor,
|
||||||
var series: List<Square>,
|
var series: List<Square>,
|
||||||
var defaultSquare: Square,
|
var defaultSquare: Square,
|
||||||
|
var hasNotes: List<Boolean>,
|
||||||
var theme: Theme,
|
var theme: Theme,
|
||||||
var today: LocalDate,
|
var today: LocalDate,
|
||||||
var onDateClickedListener: OnDateClickedListener = OnDateClickedListener { },
|
var onDateClickedListener: OnDateClickedListener = OnDateClickedListener { _, _ -> },
|
||||||
var padding: Double = 0.0,
|
var padding: Double = 0.0,
|
||||||
) : DataView {
|
) : DataView {
|
||||||
|
|
||||||
@@ -72,6 +73,14 @@ class HistoryChart(
|
|||||||
get() = squareSpacing + squareSize
|
get() = squareSpacing + squareSize
|
||||||
|
|
||||||
override fun onClick(x: Double, y: Double) {
|
override fun onClick(x: Double, y: Double) {
|
||||||
|
onDateClicked(x, y, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLongClick(x: Double, y: Double) {
|
||||||
|
onDateClicked(x, y, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onDateClicked(x: Double, y: Double, isLongClick: Boolean) {
|
||||||
if (width <= 0.0) throw IllegalStateException("onClick must be called after draw(canvas)")
|
if (width <= 0.0) throw IllegalStateException("onClick must be called after draw(canvas)")
|
||||||
val col = ((x - padding) / squareSize).toInt()
|
val col = ((x - padding) / squareSize).toInt()
|
||||||
val row = ((y - padding) / squareSize).toInt()
|
val row = ((y - padding) / squareSize).toInt()
|
||||||
@@ -79,7 +88,7 @@ class HistoryChart(
|
|||||||
if (row == 0 || col == nColumns) return
|
if (row == 0 || col == nColumns) return
|
||||||
val clickedDate = topLeftDate.plus(offset)
|
val clickedDate = topLeftDate.plus(offset)
|
||||||
if (clickedDate.isNewerThan(today)) return
|
if (clickedDate.isNewerThan(today)) return
|
||||||
onDateClickedListener.onDateClicked(clickedDate)
|
onDateClickedListener.onDateClicked(clickedDate, isLongClick)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun draw(canvas: Canvas) {
|
override fun draw(canvas: Canvas) {
|
||||||
@@ -191,7 +200,9 @@ class HistoryChart(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
val value = if (offset >= series.size) defaultSquare else series[offset]
|
val value = if (offset >= series.size) defaultSquare else series[offset]
|
||||||
|
val notes = if (offset >= hasNotes.size) false else hasNotes[offset]
|
||||||
val squareColor: Color
|
val squareColor: Color
|
||||||
|
val circleColor: Color
|
||||||
val color = theme.color(paletteColor.paletteIndex)
|
val color = theme.color(paletteColor.paletteIndex)
|
||||||
squareColor = when (value) {
|
squareColor = when (value) {
|
||||||
Square.ON -> {
|
Square.ON -> {
|
||||||
@@ -235,5 +246,14 @@ class HistoryChart(
|
|||||||
canvas.setColor(textColor)
|
canvas.setColor(textColor)
|
||||||
canvas.setTextAlign(TextAlign.CENTER)
|
canvas.setTextAlign(TextAlign.CENTER)
|
||||||
canvas.drawText(date.day.toString(), x + width / 2, y + width / 2)
|
canvas.drawText(date.day.toString(), x + width / 2, y + width / 2)
|
||||||
|
|
||||||
|
if (notes) {
|
||||||
|
circleColor = when (value) {
|
||||||
|
Square.ON -> theme.lowContrastTextColor
|
||||||
|
else -> color
|
||||||
|
}
|
||||||
|
canvas.setColor(circleColor)
|
||||||
|
canvas.fillCircle(x + width - width / 5, y + width / 5, width / 12)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user