mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 01:08:50 -06:00
Compare commits
6 Commits
5aa8744ef4
...
543be48cb1
| Author | SHA1 | Date | |
|---|---|---|---|
| 543be48cb1 | |||
| 297a381e67 | |||
| 542750207e | |||
| 46a3b69971 | |||
|
|
0a4086ec8c | ||
|
|
c987144f4a |
31
.github/workflows/main.yml
vendored
31
.github/workflows/main.yml
vendored
@@ -1,31 +0,0 @@
|
|||||||
name: Build & Test
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
paths-ignore:
|
|
||||||
- '**.md'
|
|
||||||
push:
|
|
||||||
paths-ignore:
|
|
||||||
- '**.md'
|
|
||||||
jobs:
|
|
||||||
Test:
|
|
||||||
runs-on: self-hosted
|
|
||||||
timeout-minutes: 30
|
|
||||||
steps:
|
|
||||||
- name: Check out source code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Build project
|
|
||||||
run: ./build.sh build
|
|
||||||
|
|
||||||
- name: Run Android tests
|
|
||||||
run: ./build.sh android-tests-parallel 28 29 30 32 33 34
|
|
||||||
|
|
||||||
- name: Upload artifacts
|
|
||||||
if: always()
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: build
|
|
||||||
path: |
|
|
||||||
build/*log
|
|
||||||
uhabits-android/build/outputs
|
|
||||||
|
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
<h1 align="center">Loop Habit Tracker</h1>
|
<h1 align="center">Loop Habit Tracker</h1>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/iSoron/uhabits/actions?query=workflow%3A%22Build+%26+Test%22">
|
|
||||||
<img alt="Build & Test" src="https://github.com/iSoron/uhabits/workflows/Build%20&%20Test/badge.svg" />
|
|
||||||
</a>
|
|
||||||
<a href="https://github.com/iSoron/uhabits/releases/latest">
|
<a href="https://github.com/iSoron/uhabits/releases/latest">
|
||||||
<img alt="release" src="https://img.shields.io/github/v/release/iSoron/uhabits" />
|
<img alt="release" src="https://img.shields.io/github/v/release/iSoron/uhabits" />
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -203,7 +203,8 @@ class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getPopupAnchor(): View? {
|
private fun getPopupAnchor(): View? {
|
||||||
val dialog = supportFragmentManager.findFragmentByTag("historyEditor") as HistoryEditorDialog?
|
val dialog =
|
||||||
|
supportFragmentManager.findFragmentByTag("historyEditor") as HistoryEditorDialog?
|
||||||
return dialog?.dataView
|
return dialog?.dataView
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,6 +217,25 @@ class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener {
|
|||||||
ShowHabitMenuPresenter.Message.COULD_NOT_EXPORT -> {
|
ShowHabitMenuPresenter.Message.COULD_NOT_EXPORT -> {
|
||||||
showMessage(resources.getString(R.string.could_not_export))
|
showMessage(resources.getString(R.string.could_not_export))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ShowHabitMenuPresenter.Message.HABIT_ARCHIVED -> {
|
||||||
|
showMessage(
|
||||||
|
resources.getQuantityString(
|
||||||
|
R.plurals.toast_habits_archived,
|
||||||
|
1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowHabitMenuPresenter.Message.HABIT_UNARCHIVED -> {
|
||||||
|
showMessage(
|
||||||
|
resources.getQuantityString(
|
||||||
|
R.plurals.toast_habits_unarchived,
|
||||||
|
1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ class ShowHabitMenu(
|
|||||||
if (preferences.isDeveloper) {
|
if (preferences.isDeveloper) {
|
||||||
menu.findItem(R.id.action_randomize).isVisible = true
|
menu.findItem(R.id.action_randomize).isVisible = true
|
||||||
}
|
}
|
||||||
|
menu.findItem(R.id.action_archive_habit).isVisible = presenter.canArchive()
|
||||||
|
menu.findItem(R.id.action_unarchive_habit).isVisible = presenter.canUnarchive()
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,6 +47,15 @@ class ShowHabitMenu(
|
|||||||
presenter.onEditHabit()
|
presenter.onEditHabit()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
R.id.action_archive_habit -> {
|
||||||
|
presenter.onArchiveHabits()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.action_unarchive_habit -> {
|
||||||
|
presenter.onUnarchiveHabits()
|
||||||
|
return true
|
||||||
|
}
|
||||||
R.id.action_delete -> {
|
R.id.action_delete -> {
|
||||||
presenter.onDeleteHabit()
|
presenter.onDeleteHabit()
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -94,8 +94,9 @@
|
|||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/nameInput"
|
android:id="@+id/nameInput"
|
||||||
style="@style/FormInput"
|
style="@style/FormInput"
|
||||||
android:maxLines="1"
|
android:maxLines="2"
|
||||||
android:inputType="textCapSentences"
|
android:maxLength="50"
|
||||||
|
android:inputType="textCapSentences|textMultiLine"
|
||||||
android:hint="@string/yes_or_no_short_example"
|
android:hint="@string/yes_or_no_short_example"
|
||||||
/>
|
/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -26,6 +26,16 @@
|
|||||||
android:title="@string/export"
|
android:title="@string/export"
|
||||||
app:showAsAction="never"/>
|
app:showAsAction="never"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_archive_habit"
|
||||||
|
android:title="@string/archive"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_unarchive_habit"
|
||||||
|
android:title="@string/unarchive"
|
||||||
|
app:showAsAction="never"/>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_delete"
|
android:id="@+id/action_delete"
|
||||||
android:title="@string/delete"
|
android:title="@string/delete"
|
||||||
|
|||||||
@@ -18,8 +18,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.core.ui.screens.habits.show
|
package org.isoron.uhabits.core.ui.screens.habits.show
|
||||||
|
|
||||||
|
import org.isoron.uhabits.core.commands.ArchiveHabitsCommand
|
||||||
import org.isoron.uhabits.core.commands.CommandRunner
|
import org.isoron.uhabits.core.commands.CommandRunner
|
||||||
import org.isoron.uhabits.core.commands.DeleteHabitsCommand
|
import org.isoron.uhabits.core.commands.DeleteHabitsCommand
|
||||||
|
import org.isoron.uhabits.core.commands.UnarchiveHabitsCommand
|
||||||
import org.isoron.uhabits.core.models.Entry
|
import org.isoron.uhabits.core.models.Entry
|
||||||
import org.isoron.uhabits.core.models.Habit
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import org.isoron.uhabits.core.models.HabitList
|
import org.isoron.uhabits.core.models.HabitList
|
||||||
@@ -40,10 +42,24 @@ class ShowHabitMenuPresenter(
|
|||||||
private val system: System,
|
private val system: System,
|
||||||
private val taskRunner: TaskRunner
|
private val taskRunner: TaskRunner
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
fun canArchive(): Boolean {
|
||||||
|
return !(habit.isArchived)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun canUnarchive(): Boolean {
|
||||||
|
return habit.isArchived
|
||||||
|
}
|
||||||
|
|
||||||
fun onEditHabit() {
|
fun onEditHabit() {
|
||||||
screen.showEditHabitScreen(habit)
|
screen.showEditHabitScreen(habit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onArchiveHabits() {
|
||||||
|
commandRunner.run(ArchiveHabitsCommand(habitList, listOf(habit)))
|
||||||
|
screen.showMessage(Message.HABIT_ARCHIVED)
|
||||||
|
}
|
||||||
|
|
||||||
fun onExportCSV() {
|
fun onExportCSV() {
|
||||||
val outputDir = system.getCSVOutputDir()
|
val outputDir = system.getCSVOutputDir()
|
||||||
taskRunner.execute(
|
taskRunner.execute(
|
||||||
@@ -64,6 +80,11 @@ class ShowHabitMenuPresenter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onUnarchiveHabits() {
|
||||||
|
commandRunner.run(UnarchiveHabitsCommand(habitList, listOf(habit)))
|
||||||
|
screen.showMessage(Message.HABIT_UNARCHIVED)
|
||||||
|
}
|
||||||
|
|
||||||
fun onRandomize() {
|
fun onRandomize() {
|
||||||
val random = Random()
|
val random = Random()
|
||||||
habit.originalEntries.clear()
|
habit.originalEntries.clear()
|
||||||
@@ -72,7 +93,10 @@ class ShowHabitMenuPresenter(
|
|||||||
if (i % 7 == 0) strength = max(0.0, min(100.0, strength + 10 * random.nextGaussian()))
|
if (i % 7 == 0) strength = max(0.0, min(100.0, strength + 10 * random.nextGaussian()))
|
||||||
if (random.nextInt(100) > strength) continue
|
if (random.nextInt(100) > strength) continue
|
||||||
var value = Entry.YES_MANUAL
|
var value = Entry.YES_MANUAL
|
||||||
if (habit.isNumerical) value = (1000 + 250 * random.nextGaussian() * strength / 100).toInt() * 1000
|
if (habit.isNumerical) {
|
||||||
|
value =
|
||||||
|
(1000 + 250 * random.nextGaussian() * strength / 100).toInt() * 1000
|
||||||
|
}
|
||||||
habit.originalEntries.add(Entry(DateUtils.getToday().minus(i), value))
|
habit.originalEntries.add(Entry(DateUtils.getToday().minus(i), value))
|
||||||
}
|
}
|
||||||
habit.recompute()
|
habit.recompute()
|
||||||
@@ -80,7 +104,9 @@ class ShowHabitMenuPresenter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum class Message {
|
enum class Message {
|
||||||
COULD_NOT_EXPORT
|
COULD_NOT_EXPORT,
|
||||||
|
HABIT_ARCHIVED,
|
||||||
|
HABIT_UNARCHIVED
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Screen {
|
interface Screen {
|
||||||
|
|||||||
Reference in New Issue
Block a user