mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-08 18:18:52 -06:00
Compare commits
11 Commits
fix/stackw
...
feature/ca
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3aa4dee18 | ||
|
|
739676ab1a | ||
|
|
c091c16ffd | ||
|
|
a767e433d2 | ||
|
|
e189d17fd5 | ||
|
|
30c39853e9 | ||
|
|
c1fa6c46ee | ||
|
|
6e4ed3837f | ||
|
|
cb65604581 | ||
|
|
2db4491328 | ||
|
|
25a3509988 |
@@ -21,7 +21,6 @@ package org.isoron.uhabits.activities.habits.list
|
|||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
@@ -85,6 +84,7 @@ class ListHabitsActivity : AppCompatActivity(), Preferences.Listener {
|
|||||||
Thread.setDefaultUncaughtExceptionHandler(BaseExceptionHandler(this))
|
Thread.setDefaultUncaughtExceptionHandler(BaseExceptionHandler(this))
|
||||||
component.listHabitsBehavior.onStartup()
|
component.listHabitsBehavior.onStartup()
|
||||||
setContentView(rootView)
|
setContentView(rootView)
|
||||||
|
parseIntents()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
@@ -100,16 +100,11 @@ class ListHabitsActivity : AppCompatActivity(), Preferences.Listener {
|
|||||||
rootView.postInvalidate()
|
rootView.postInvalidate()
|
||||||
midnightTimer.onResume()
|
midnightTimer.onResume()
|
||||||
taskRunner.run {
|
taskRunner.run {
|
||||||
try {
|
AutoBackup(this@ListHabitsActivity).run()
|
||||||
AutoBackup(this@ListHabitsActivity).run()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e("ListHabitActivity", "AutoBackup task failed", e)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (prefs.theme == THEME_DARK && prefs.isPureBlackEnabled != pureBlack) {
|
if (prefs.theme == THEME_DARK && prefs.isPureBlackEnabled != pureBlack) {
|
||||||
restartWithFade(ListHabitsActivity::class.java)
|
restartWithFade(ListHabitsActivity::class.java)
|
||||||
}
|
}
|
||||||
parseIntents()
|
|
||||||
super.onResume()
|
super.onResume()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +124,6 @@ class ListHabitsActivity : AppCompatActivity(), Preferences.Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun parseIntents() {
|
private fun parseIntents() {
|
||||||
if (intent == null) return
|
|
||||||
if (intent.action == ACTION_EDIT) {
|
if (intent.action == ACTION_EDIT) {
|
||||||
val habitId = intent.extras?.getLong("habit")
|
val habitId = intent.extras?.getLong("habit")
|
||||||
val timestamp = intent.extras?.getLong("timestamp")
|
val timestamp = intent.extras?.getLong("timestamp")
|
||||||
@@ -138,12 +132,6 @@ class ListHabitsActivity : AppCompatActivity(), Preferences.Listener {
|
|||||||
component.listHabitsBehavior.onEdit(habit, Timestamp(timestamp))
|
component.listHabitsBehavior.onEdit(habit, Timestamp(timestamp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
intent = null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNewIntent(intent: Intent?) {
|
|
||||||
super.onNewIntent(intent)
|
|
||||||
setIntent(intent)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -21,16 +21,13 @@ package org.isoron.uhabits.intents
|
|||||||
|
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.app.PendingIntent.FLAG_IMMUTABLE
|
import android.app.PendingIntent.FLAG_IMMUTABLE
|
||||||
import android.app.PendingIntent.FLAG_MUTABLE
|
|
||||||
import android.app.PendingIntent.FLAG_UPDATE_CURRENT
|
import android.app.PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
import android.app.PendingIntent.getActivity
|
import android.app.PendingIntent.getActivity
|
||||||
import android.app.PendingIntent.getBroadcast
|
import android.app.PendingIntent.getBroadcast
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
|
||||||
import org.isoron.uhabits.activities.habits.list.ListHabitsActivity
|
import org.isoron.uhabits.activities.habits.list.ListHabitsActivity
|
||||||
import org.isoron.uhabits.activities.habits.show.ShowHabitActivity
|
|
||||||
import org.isoron.uhabits.core.AppScope
|
import org.isoron.uhabits.core.AppScope
|
||||||
import org.isoron.uhabits.core.models.Habit
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import org.isoron.uhabits.core.models.Timestamp
|
import org.isoron.uhabits.core.models.Timestamp
|
||||||
@@ -92,20 +89,6 @@ class PendingIntentFactory
|
|||||||
)
|
)
|
||||||
.getPendingIntent(0, FLAG_IMMUTABLE or FLAG_UPDATE_CURRENT)!!
|
.getPendingIntent(0, FLAG_IMMUTABLE or FLAG_UPDATE_CURRENT)!!
|
||||||
|
|
||||||
fun showHabitTemplate(): PendingIntent {
|
|
||||||
return getActivity(
|
|
||||||
context,
|
|
||||||
0,
|
|
||||||
Intent(context, ShowHabitActivity::class.java),
|
|
||||||
getIntentTemplateFlags()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun showHabitFillIn(habit: Habit) =
|
|
||||||
Intent().apply {
|
|
||||||
data = Uri.parse(habit.uriString)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun showReminder(
|
fun showReminder(
|
||||||
habit: Habit,
|
habit: Habit,
|
||||||
reminderTime: Long?,
|
reminderTime: Long?,
|
||||||
@@ -159,7 +142,7 @@ class PendingIntentFactory
|
|||||||
fun showNumberPicker(habit: Habit, timestamp: Timestamp): PendingIntent? {
|
fun showNumberPicker(habit: Habit, timestamp: Timestamp): PendingIntent? {
|
||||||
return getActivity(
|
return getActivity(
|
||||||
context,
|
context,
|
||||||
(habit.id!! % Integer.MAX_VALUE).toInt() + 1,
|
0,
|
||||||
Intent(context, ListHabitsActivity::class.java).apply {
|
Intent(context, ListHabitsActivity::class.java).apply {
|
||||||
action = ListHabitsActivity.ACTION_EDIT
|
action = ListHabitsActivity.ACTION_EDIT
|
||||||
putExtra("habit", habit.id)
|
putExtra("habit", habit.id)
|
||||||
@@ -168,43 +151,4 @@ class PendingIntentFactory
|
|||||||
FLAG_IMMUTABLE or FLAG_UPDATE_CURRENT
|
FLAG_IMMUTABLE or FLAG_UPDATE_CURRENT
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showNumberPickerTemplate(): PendingIntent {
|
|
||||||
return getActivity(
|
|
||||||
context,
|
|
||||||
1,
|
|
||||||
Intent(context, ListHabitsActivity::class.java).apply {
|
|
||||||
action = ListHabitsActivity.ACTION_EDIT
|
|
||||||
},
|
|
||||||
getIntentTemplateFlags()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun showNumberPickerFillIn(habit: Habit, timestamp: Timestamp) = Intent().apply {
|
|
||||||
putExtra("habit", habit.id)
|
|
||||||
putExtra("timestamp", timestamp.unixTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getIntentTemplateFlags(): Int {
|
|
||||||
var flags = 0
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
||||||
flags = flags or FLAG_MUTABLE
|
|
||||||
}
|
|
||||||
return flags
|
|
||||||
}
|
|
||||||
|
|
||||||
fun toggleCheckmarkTemplate(): PendingIntent =
|
|
||||||
getBroadcast(
|
|
||||||
context,
|
|
||||||
2,
|
|
||||||
Intent(context, WidgetReceiver::class.java).apply {
|
|
||||||
action = WidgetReceiver.ACTION_TOGGLE_REPETITION
|
|
||||||
},
|
|
||||||
getIntentTemplateFlags()
|
|
||||||
)
|
|
||||||
|
|
||||||
fun toggleCheckmarkFillIn(habit: Habit, timestamp: Timestamp) = Intent().apply {
|
|
||||||
data = Uri.parse(habit.uriString)
|
|
||||||
putExtra("timestamp", timestamp.unixTime)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,10 +73,6 @@ class StackWidget(
|
|||||||
StackWidgetType.getStackWidgetAdapterViewId(widgetType),
|
StackWidgetType.getStackWidgetAdapterViewId(widgetType),
|
||||||
StackWidgetType.getStackWidgetEmptyViewId(widgetType)
|
StackWidgetType.getStackWidgetEmptyViewId(widgetType)
|
||||||
)
|
)
|
||||||
remoteViews.setPendingIntentTemplate(
|
|
||||||
StackWidgetType.getStackWidgetAdapterViewId(widgetType),
|
|
||||||
StackWidgetType.getPendingIntentTemplate(pendingIntentFactory, widgetType, habits)
|
|
||||||
)
|
|
||||||
return remoteViews
|
return remoteViews
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,14 +29,11 @@ import android.widget.RemoteViewsService
|
|||||||
import android.widget.RemoteViewsService.RemoteViewsFactory
|
import android.widget.RemoteViewsService.RemoteViewsFactory
|
||||||
import org.isoron.platform.utils.StringUtils.Companion.splitLongs
|
import org.isoron.platform.utils.StringUtils.Companion.splitLongs
|
||||||
import org.isoron.uhabits.HabitsApplication
|
import org.isoron.uhabits.HabitsApplication
|
||||||
import org.isoron.uhabits.R
|
|
||||||
import org.isoron.uhabits.core.models.Habit
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import org.isoron.uhabits.core.models.HabitNotFoundException
|
import org.isoron.uhabits.core.models.HabitNotFoundException
|
||||||
import org.isoron.uhabits.core.preferences.Preferences
|
import org.isoron.uhabits.core.preferences.Preferences
|
||||||
import org.isoron.uhabits.core.utils.DateUtils.Companion.getToday
|
|
||||||
import org.isoron.uhabits.intents.IntentFactory
|
|
||||||
import org.isoron.uhabits.intents.PendingIntentFactory
|
|
||||||
import org.isoron.uhabits.utils.InterfaceUtils.dpToPixels
|
import org.isoron.uhabits.utils.InterfaceUtils.dpToPixels
|
||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
class StackWidgetService : RemoteViewsService() {
|
class StackWidgetService : RemoteViewsService() {
|
||||||
override fun onGetViewFactory(intent: Intent): RemoteViewsFactory {
|
override fun onGetViewFactory(intent: Intent): RemoteViewsFactory {
|
||||||
@@ -57,6 +54,7 @@ internal class StackRemoteViewsFactory(private val context: Context, intent: Int
|
|||||||
)
|
)
|
||||||
private val habitIds: LongArray
|
private val habitIds: LongArray
|
||||||
private val widgetType: StackWidgetType
|
private val widgetType: StackWidgetType
|
||||||
|
private var remoteViews = ArrayList<RemoteViews>()
|
||||||
override fun onCreate() {}
|
override fun onCreate() {}
|
||||||
override fun onDestroy() {}
|
override fun onDestroy() {}
|
||||||
override fun getCount(): Int {
|
override fun getCount(): Int {
|
||||||
@@ -87,26 +85,8 @@ internal class StackRemoteViewsFactory(private val context: Context, intent: Int
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getViewAt(position: Int): RemoteViews? {
|
override fun getViewAt(position: Int): RemoteViews? {
|
||||||
Log.i("StackRemoteViewsFactory", "getViewAt $position started")
|
Log.i("StackRemoteViewsFactory", "getViewAt $position")
|
||||||
if (position < 0 || position >= habitIds.size) return null
|
return if (0 <= position && position < remoteViews.size) remoteViews[position] else null
|
||||||
val app = context.applicationContext as HabitsApplication
|
|
||||||
val prefs = app.component.preferences
|
|
||||||
val habitList = app.component.habitList
|
|
||||||
val options = AppWidgetManager.getInstance(context).getAppWidgetOptions(widgetId)
|
|
||||||
if (Looper.myLooper() == null) Looper.prepare()
|
|
||||||
val habits = habitIds.map { habitList.getById(it) ?: throw HabitNotFoundException() }
|
|
||||||
val h = habits[position]
|
|
||||||
val widget = constructWidget(h, prefs)
|
|
||||||
widget.setDimensions(getDimensionsFromOptions(context, options))
|
|
||||||
val landscapeViews = widget.landscapeRemoteViews
|
|
||||||
val portraitViews = widget.portraitRemoteViews
|
|
||||||
val factory = PendingIntentFactory(context, IntentFactory())
|
|
||||||
val intent = StackWidgetType.getIntentFillIn(factory, widgetType, h, habits, getToday())
|
|
||||||
landscapeViews.setOnClickFillInIntent(R.id.button, intent)
|
|
||||||
portraitViews.setOnClickFillInIntent(R.id.button, intent)
|
|
||||||
val remoteViews = RemoteViews(landscapeViews, portraitViews)
|
|
||||||
Log.i("StackRemoteViewsFactory", "getViewAt $position ended")
|
|
||||||
return remoteViews
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun constructWidget(
|
private fun constructWidget(
|
||||||
@@ -151,6 +131,24 @@ internal class StackRemoteViewsFactory(private val context: Context, intent: Int
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onDataSetChanged() {
|
override fun onDataSetChanged() {
|
||||||
|
Log.i("StackRemoteViewsFactory", "onDataSetChanged started")
|
||||||
|
val app = context.applicationContext as HabitsApplication
|
||||||
|
val prefs = app.component.preferences
|
||||||
|
val habitList = app.component.habitList
|
||||||
|
val options = AppWidgetManager.getInstance(context).getAppWidgetOptions(widgetId)
|
||||||
|
val newRemoteViews = ArrayList<RemoteViews>()
|
||||||
|
if (Looper.myLooper() == null) Looper.prepare()
|
||||||
|
for (id in habitIds) {
|
||||||
|
val h = habitList.getById(id) ?: throw HabitNotFoundException()
|
||||||
|
val widget = constructWidget(h, prefs)
|
||||||
|
widget.setDimensions(getDimensionsFromOptions(context, options))
|
||||||
|
val landscapeViews = widget.landscapeRemoteViews
|
||||||
|
val portraitViews = widget.portraitRemoteViews
|
||||||
|
newRemoteViews.add(RemoteViews(landscapeViews, portraitViews))
|
||||||
|
Log.i("StackRemoteViewsFactory", "onDataSetChanged constructed widget $id")
|
||||||
|
}
|
||||||
|
remoteViews = newRemoteViews
|
||||||
|
Log.i("StackRemoteViewsFactory", "onDataSetChanged ended")
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|||||||
@@ -18,12 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.widgets
|
package org.isoron.uhabits.widgets
|
||||||
|
|
||||||
import android.app.PendingIntent
|
|
||||||
import android.content.Intent
|
|
||||||
import org.isoron.uhabits.R
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.core.models.Habit
|
|
||||||
import org.isoron.uhabits.core.models.Timestamp
|
|
||||||
import org.isoron.uhabits.intents.PendingIntentFactory
|
|
||||||
import java.lang.IllegalStateException
|
import java.lang.IllegalStateException
|
||||||
|
|
||||||
enum class StackWidgetType(val value: Int) {
|
enum class StackWidgetType(val value: Int) {
|
||||||
@@ -78,39 +73,5 @@ enum class StackWidgetType(val value: Int) {
|
|||||||
else -> throw IllegalStateException()
|
else -> throw IllegalStateException()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getPendingIntentTemplate(
|
|
||||||
factory: PendingIntentFactory,
|
|
||||||
widgetType: StackWidgetType,
|
|
||||||
habits: List<Habit>
|
|
||||||
): PendingIntent {
|
|
||||||
val containsNumerical = habits.any { it.isNumerical }
|
|
||||||
return when (widgetType) {
|
|
||||||
CHECKMARK -> if (containsNumerical) {
|
|
||||||
factory.showNumberPickerTemplate()
|
|
||||||
} else {
|
|
||||||
factory.toggleCheckmarkTemplate()
|
|
||||||
}
|
|
||||||
FREQUENCY, SCORE, HISTORY, STREAKS, TARGET -> factory.showHabitTemplate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getIntentFillIn(
|
|
||||||
factory: PendingIntentFactory,
|
|
||||||
widgetType: StackWidgetType,
|
|
||||||
habit: Habit,
|
|
||||||
allHabitsInStackWidget: List<Habit>,
|
|
||||||
timestamp: Timestamp
|
|
||||||
): Intent {
|
|
||||||
val containsNumerical = allHabitsInStackWidget.any { it.isNumerical }
|
|
||||||
return when (widgetType) {
|
|
||||||
CHECKMARK -> if (containsNumerical) {
|
|
||||||
factory.showNumberPickerFillIn(habit, timestamp)
|
|
||||||
} else {
|
|
||||||
factory.toggleCheckmarkFillIn(habit, timestamp)
|
|
||||||
}
|
|
||||||
FREQUENCY, SCORE, HISTORY, STREAKS, TARGET -> factory.showHabitFillIn(habit)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,12 +25,6 @@ class StringUtils {
|
|||||||
|
|
||||||
fun joinLongs(values: LongArray): String = values.joinToString(separator = ",")
|
fun joinLongs(values: LongArray): String = values.joinToString(separator = ",")
|
||||||
|
|
||||||
fun splitLongs(str: String): LongArray {
|
fun splitLongs(str: String): LongArray = str.split(",").map { it.toLong() }.toLongArray()
|
||||||
return try {
|
|
||||||
str.split(",").map { it.toLong() }.toLongArray()
|
|
||||||
} catch (e: NumberFormatException) {
|
|
||||||
LongArray(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user