mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 01:08:50 -06:00
Merge branch 'dev'
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
VERSION_CODE = 46
|
||||
VERSION_NAME = 1.8.3
|
||||
VERSION_CODE = 47
|
||||
VERSION_NAME = 1.8.4
|
||||
|
||||
MIN_SDK_VERSION = 21
|
||||
TARGET_SDK_VERSION = 29
|
||||
|
||||
@@ -25,7 +25,6 @@ import android.graphics.*
|
||||
import android.graphics.BitmapFactory.*
|
||||
import android.os.*
|
||||
import android.os.Build.VERSION.*
|
||||
import android.support.annotation.*
|
||||
import android.support.v4.app.*
|
||||
import android.support.v4.app.NotificationCompat.*
|
||||
import android.util.*
|
||||
@@ -38,9 +37,6 @@ import org.isoron.uhabits.core.ui.*
|
||||
import org.isoron.uhabits.intents.*
|
||||
import javax.inject.*
|
||||
|
||||
|
||||
|
||||
|
||||
@AppScope
|
||||
class AndroidNotificationTray
|
||||
@Inject constructor(
|
||||
@@ -48,7 +44,7 @@ class AndroidNotificationTray
|
||||
private val pendingIntents: PendingIntentFactory,
|
||||
private val preferences: Preferences,
|
||||
private val ringtoneManager: RingtoneManager
|
||||
) : NotificationTray.SystemTray {
|
||||
) : NotificationTray.SystemTray {
|
||||
private var active = HashSet<Int>()
|
||||
|
||||
override fun log(msg: String) {
|
||||
@@ -62,16 +58,15 @@ class AndroidNotificationTray
|
||||
active.remove(id)
|
||||
|
||||
// Clear the group summary notification
|
||||
if(active.isEmpty()) manager.cancelAll()
|
||||
if (active.isEmpty()) manager.cancelAll()
|
||||
}
|
||||
|
||||
override fun showNotification(habit: Habit,
|
||||
notificationId: Int,
|
||||
timestamp: Timestamp,
|
||||
reminderTime: Long)
|
||||
{
|
||||
reminderTime: Long) {
|
||||
val notificationManager = NotificationManagerCompat.from(context)
|
||||
val summary = buildSummary(reminderTime)
|
||||
val summary = buildSummary(habit, reminderTime)
|
||||
notificationManager.notify(Int.MAX_VALUE, summary)
|
||||
val notification = buildNotification(habit, reminderTime, timestamp)
|
||||
createAndroidNotificationChannel(context)
|
||||
@@ -79,20 +74,22 @@ class AndroidNotificationTray
|
||||
notificationManager.notify(notificationId, notification)
|
||||
} catch (e: RuntimeException) {
|
||||
// Some Xiaomi phones produce a RuntimeException if custom notification sounds are used.
|
||||
Log.i("AndroidNotificationTray", "Failed to show notification. Retrying without sound.")
|
||||
val n = buildNotification(habit, reminderTime, timestamp, disableSound = true)
|
||||
Log.i("AndroidNotificationTray",
|
||||
"Failed to show notification. Retrying without sound.")
|
||||
val n = buildNotification(habit,
|
||||
reminderTime,
|
||||
timestamp,
|
||||
disableSound = true)
|
||||
notificationManager.notify(notificationId, n)
|
||||
|
||||
}
|
||||
active.add(notificationId)
|
||||
}
|
||||
|
||||
@NonNull
|
||||
fun buildNotification(@NonNull habit: Habit,
|
||||
@NonNull reminderTime: Long,
|
||||
@NonNull timestamp: Timestamp,
|
||||
disableSound: Boolean = false) : Notification
|
||||
{
|
||||
fun buildNotification(habit: Habit,
|
||||
reminderTime: Long,
|
||||
timestamp: Timestamp,
|
||||
disableSound: Boolean = false): Notification {
|
||||
|
||||
val addRepetitionAction = Action(
|
||||
R.drawable.ic_action_check,
|
||||
@@ -114,10 +111,11 @@ class AndroidNotificationTray
|
||||
.addAction(addRepetitionAction)
|
||||
.addAction(removeRepetitionAction)
|
||||
|
||||
val defaultText = context.getString(R.string.default_reminder_question)
|
||||
val builder = NotificationCompat.Builder(context, REMINDERS_CHANNEL_ID)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setContentTitle(habit.name)
|
||||
.setContentText(habit.description)
|
||||
.setContentText(if(habit.description.isBlank()) defaultText else habit.description)
|
||||
.setContentIntent(pendingIntents.showHabit(habit))
|
||||
.setDeleteIntent(pendingIntents.dismissNotification(habit))
|
||||
.addAction(addRepetitionAction)
|
||||
@@ -126,7 +124,7 @@ class AndroidNotificationTray
|
||||
.setWhen(reminderTime)
|
||||
.setShowWhen(true)
|
||||
.setOngoing(preferences.shouldMakeNotificationsSticky())
|
||||
.setGroup("default")
|
||||
.setGroup("group" + habit.getId())
|
||||
|
||||
if (!disableSound)
|
||||
builder.setSound(ringtoneManager.getURI())
|
||||
@@ -134,41 +132,39 @@ class AndroidNotificationTray
|
||||
if (preferences.shouldMakeNotificationsLed())
|
||||
builder.setLights(Color.RED, 1000, 1000)
|
||||
|
||||
if(SDK_INT < Build.VERSION_CODES.O) {
|
||||
if (SDK_INT < Build.VERSION_CODES.O) {
|
||||
val snoozeAction = Action(R.drawable.ic_action_snooze,
|
||||
context.getString(R.string.snooze),
|
||||
pendingIntents.snoozeNotification(habit))
|
||||
context.getString(R.string.snooze),
|
||||
pendingIntents.snoozeNotification(habit))
|
||||
wearableExtender.addAction(snoozeAction)
|
||||
builder.addAction(snoozeAction)
|
||||
}
|
||||
|
||||
builder.extend(wearableExtender)
|
||||
return builder.build()
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private fun buildSummary(@NonNull reminderTime: Long) : Notification
|
||||
{
|
||||
private fun buildSummary(habit: Habit,
|
||||
reminderTime: Long): Notification {
|
||||
return NotificationCompat.Builder(context, REMINDERS_CHANNEL_ID)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setContentTitle(context.getString(R.string.app_name))
|
||||
.setWhen(reminderTime)
|
||||
.setShowWhen(true)
|
||||
.setGroup("default")
|
||||
.setGroup("group" + habit.getId())
|
||||
.setGroupSummary(true)
|
||||
.build()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val REMINDERS_CHANNEL_ID = "REMINDERS"
|
||||
private const val REMINDERS_CHANNEL_ID = "REMINDERS"
|
||||
fun createAndroidNotificationChannel(context: Context) {
|
||||
val notificationManager = context.getSystemService(Activity.NOTIFICATION_SERVICE)
|
||||
as NotificationManager
|
||||
if (SDK_INT >= Build.VERSION_CODES.O)
|
||||
{
|
||||
if (SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val channel = NotificationChannel(REMINDERS_CHANNEL_ID,
|
||||
context.resources.getString(R.string.reminder),
|
||||
NotificationManager.IMPORTANCE_DEFAULT)
|
||||
context.resources.getString(R.string.reminder),
|
||||
NotificationManager.IMPORTANCE_DEFAULT)
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,6 @@ public class ReminderReceiver extends BroadcastReceiver
|
||||
case ACTION_SHOW_REMINDER:
|
||||
if (habit == null) return;
|
||||
Log.d("ReminderReceiver", String.format(
|
||||
Locale.US,
|
||||
"onShowReminder habit=%d timestamp=%d reminderTime=%d",
|
||||
habit.id,
|
||||
timestamp,
|
||||
@@ -88,15 +87,18 @@ public class ReminderReceiver extends BroadcastReceiver
|
||||
|
||||
case ACTION_DISMISS_REMINDER:
|
||||
if (habit == null) return;
|
||||
Log.d("ReminderReceiver", String.format("onDismiss habit=%d", habit.id));
|
||||
reminderController.onDismiss(habit);
|
||||
break;
|
||||
|
||||
case ACTION_SNOOZE_REMINDER:
|
||||
if (habit == null) return;
|
||||
Log.d("ReminderReceiver", String.format("onSnoozePressed habit=%d", habit.id));
|
||||
reminderController.onSnoozePressed(habit, context);
|
||||
break;
|
||||
|
||||
case Intent.ACTION_BOOT_COMPLETED:
|
||||
Log.d("ReminderReceiver", "onBootCompleted");
|
||||
reminderController.onBootCompleted();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -38,33 +38,37 @@ import dagger.*;
|
||||
public class WidgetReceiver extends BroadcastReceiver
|
||||
{
|
||||
public static final String ACTION_ADD_REPETITION =
|
||||
"org.isoron.uhabits.ACTION_ADD_REPETITION";
|
||||
"org.isoron.uhabits.ACTION_ADD_REPETITION";
|
||||
|
||||
public static final String ACTION_DISMISS_REMINDER =
|
||||
"org.isoron.uhabits.ACTION_DISMISS_REMINDER";
|
||||
"org.isoron.uhabits.ACTION_DISMISS_REMINDER";
|
||||
|
||||
public static final String ACTION_REMOVE_REPETITION =
|
||||
"org.isoron.uhabits.ACTION_REMOVE_REPETITION";
|
||||
"org.isoron.uhabits.ACTION_REMOVE_REPETITION";
|
||||
|
||||
public static final String ACTION_TOGGLE_REPETITION =
|
||||
"org.isoron.uhabits.ACTION_TOGGLE_REPETITION";
|
||||
"org.isoron.uhabits.ACTION_TOGGLE_REPETITION";
|
||||
|
||||
private static final String TAG = "WidgetReceiver";
|
||||
|
||||
@Override
|
||||
public void onReceive(final Context context, Intent intent)
|
||||
{
|
||||
HabitsApplication app =
|
||||
(HabitsApplication) context.getApplicationContext();
|
||||
(HabitsApplication) context.getApplicationContext();
|
||||
|
||||
WidgetComponent component = DaggerWidgetReceiver_WidgetComponent
|
||||
.builder()
|
||||
.habitsApplicationComponent(app.getComponent())
|
||||
.build();
|
||||
.builder()
|
||||
.habitsApplicationComponent(app.getComponent())
|
||||
.build();
|
||||
|
||||
IntentParser parser = app.getComponent().getIntentParser();
|
||||
WidgetBehavior controller = component.getWidgetController();
|
||||
Preferences prefs = app.getComponent().getPreferences();
|
||||
|
||||
if(prefs.isSyncEnabled())
|
||||
Log.i(TAG, String.format("Received intent: %s", intent.toString()));
|
||||
|
||||
if (prefs.isSyncEnabled())
|
||||
context.startService(new Intent(context, SyncService.class));
|
||||
|
||||
try
|
||||
@@ -75,18 +79,30 @@ public class WidgetReceiver extends BroadcastReceiver
|
||||
switch (intent.getAction())
|
||||
{
|
||||
case ACTION_ADD_REPETITION:
|
||||
Log.d(TAG, String.format(
|
||||
"onAddRepetition habit=%d timestamp=%d",
|
||||
data.getHabit().getId(),
|
||||
data.getTimestamp().getUnixTime()));
|
||||
controller.onAddRepetition(data.getHabit(),
|
||||
data.getTimestamp());
|
||||
data.getTimestamp());
|
||||
break;
|
||||
|
||||
case ACTION_TOGGLE_REPETITION:
|
||||
Log.d(TAG, String.format(
|
||||
"onToggleRepetition habit=%d timestamp=%d",
|
||||
data.getHabit().getId(),
|
||||
data.getTimestamp().getUnixTime()));
|
||||
controller.onToggleRepetition(data.getHabit(),
|
||||
data.getTimestamp());
|
||||
data.getTimestamp());
|
||||
break;
|
||||
|
||||
case ACTION_REMOVE_REPETITION:
|
||||
Log.d(TAG, String.format(
|
||||
"onRemoveRepetition habit=%d timestamp=%d",
|
||||
data.getHabit().getId(),
|
||||
data.getTimestamp().getUnixTime()));
|
||||
controller.onRemoveRepetition(data.getHabit(),
|
||||
data.getTimestamp());
|
||||
data.getTimestamp());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
1.8.3
|
||||
1.8.4
|
||||
* Bugfixes
|
||||
1.8:
|
||||
* New bar chart showing number of repetitions performed each week, month or year
|
||||
|
||||
@@ -243,5 +243,6 @@
|
||||
<string name="widget_opacity_title">Widget opacity</string>
|
||||
<string name="widget_opacity_description">Makes widgets more transparent or more opaque in your home screen.</string>
|
||||
<string name="first_day_of_the_week">First day of the week</string>
|
||||
<string name="default_reminder_question">Have you completed this habit today?</string>
|
||||
|
||||
</resources>
|
||||
@@ -248,8 +248,8 @@ public class HabitsCSVExporter
|
||||
continue;
|
||||
Timestamp currOld = h.getRepetitions().getOldest().getTimestamp();
|
||||
Timestamp currNew = h.getRepetitions().getNewest().getTimestamp();
|
||||
oldest = currOld.isOlderThan(oldest) ? oldest : currOld;
|
||||
newest = currNew.isNewerThan(newest) ? newest : currNew;
|
||||
oldest = currOld.isOlderThan(oldest) ? currOld : oldest;
|
||||
newest = currNew.isNewerThan(newest) ? currNew : newest;
|
||||
}
|
||||
return new Timestamp[]{oldest, newest};
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ public class HabitCardListCache implements CommandRunner.Listener
|
||||
{
|
||||
private int checkmarkCount;
|
||||
|
||||
@Nullable
|
||||
private Task currentFetchTask;
|
||||
|
||||
@NonNull
|
||||
@@ -56,13 +57,15 @@ public class HabitCardListCache implements CommandRunner.Listener
|
||||
private CacheData data;
|
||||
|
||||
@NonNull
|
||||
private HabitList allHabits;
|
||||
private final HabitList allHabits;
|
||||
|
||||
@NonNull
|
||||
private HabitList filteredHabits;
|
||||
|
||||
@NonNull
|
||||
private final TaskRunner taskRunner;
|
||||
|
||||
@NonNull
|
||||
private final CommandRunner commandRunner;
|
||||
|
||||
@Inject
|
||||
@@ -70,21 +73,27 @@ public class HabitCardListCache implements CommandRunner.Listener
|
||||
@NonNull CommandRunner commandRunner,
|
||||
@NonNull TaskRunner taskRunner)
|
||||
{
|
||||
if (allHabits == null) throw new NullPointerException();
|
||||
if (commandRunner == null) throw new NullPointerException();
|
||||
if (taskRunner == null) throw new NullPointerException();
|
||||
|
||||
this.allHabits = allHabits;
|
||||
this.commandRunner = commandRunner;
|
||||
this.filteredHabits = allHabits;
|
||||
this.taskRunner = taskRunner;
|
||||
|
||||
this.listener = new Listener() {};
|
||||
this.listener = new Listener()
|
||||
{
|
||||
};
|
||||
data = new CacheData();
|
||||
}
|
||||
|
||||
public void cancelTasks()
|
||||
public synchronized void cancelTasks()
|
||||
{
|
||||
if (currentFetchTask != null) currentFetchTask.cancel();
|
||||
}
|
||||
|
||||
public int[] getCheckmarks(long habitId)
|
||||
public synchronized int[] getCheckmarks(long habitId)
|
||||
{
|
||||
return data.checkmarks.get(habitId);
|
||||
}
|
||||
@@ -98,57 +107,57 @@ public class HabitCardListCache implements CommandRunner.Listener
|
||||
@Nullable
|
||||
public synchronized Habit getHabitByPosition(int position)
|
||||
{
|
||||
if(position < 0 || position >= data.habits.size()) return null;
|
||||
if (position < 0 || position >= data.habits.size()) return null;
|
||||
return data.habits.get(position);
|
||||
}
|
||||
|
||||
public int getHabitCount()
|
||||
public synchronized int getHabitCount()
|
||||
{
|
||||
return data.habits.size();
|
||||
}
|
||||
|
||||
public HabitList.Order getOrder()
|
||||
public synchronized HabitList.Order getOrder()
|
||||
{
|
||||
return filteredHabits.getOrder();
|
||||
}
|
||||
|
||||
public double getScore(long habitId)
|
||||
public synchronized double getScore(long habitId)
|
||||
{
|
||||
return data.scores.get(habitId);
|
||||
}
|
||||
|
||||
public void onAttached()
|
||||
public synchronized void onAttached()
|
||||
{
|
||||
refreshAllHabits();
|
||||
commandRunner.addListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandExecuted(@NonNull Command command,
|
||||
@Nullable Long refreshKey)
|
||||
public synchronized void onCommandExecuted(@Nullable Command command,
|
||||
@Nullable Long refreshKey)
|
||||
{
|
||||
if (refreshKey == null) refreshAllHabits();
|
||||
else refreshHabit(refreshKey);
|
||||
}
|
||||
|
||||
public void onDetached()
|
||||
public synchronized void onDetached()
|
||||
{
|
||||
commandRunner.removeListener(this);
|
||||
}
|
||||
|
||||
public void refreshAllHabits()
|
||||
public synchronized void refreshAllHabits()
|
||||
{
|
||||
if (currentFetchTask != null) currentFetchTask.cancel();
|
||||
currentFetchTask = new RefreshTask();
|
||||
taskRunner.execute(currentFetchTask);
|
||||
}
|
||||
|
||||
public void refreshHabit(long id)
|
||||
public synchronized void refreshHabit(long id)
|
||||
{
|
||||
taskRunner.execute(new RefreshTask(id));
|
||||
}
|
||||
|
||||
public void remove(@NonNull Long id)
|
||||
public synchronized void remove(long id)
|
||||
{
|
||||
Habit h = data.id_to_habit.get(id);
|
||||
if (h == null) return;
|
||||
@@ -162,7 +171,7 @@ public class HabitCardListCache implements CommandRunner.Listener
|
||||
listener.onItemRemoved(position);
|
||||
}
|
||||
|
||||
public void reorder(int from, int to)
|
||||
public synchronized void reorder(int from, int to)
|
||||
{
|
||||
Habit fromHabit = data.habits.get(from);
|
||||
data.habits.remove(from);
|
||||
@@ -170,23 +179,26 @@ public class HabitCardListCache implements CommandRunner.Listener
|
||||
listener.onItemMoved(from, to);
|
||||
}
|
||||
|
||||
public void setCheckmarkCount(int checkmarkCount)
|
||||
public synchronized void setCheckmarkCount(int checkmarkCount)
|
||||
{
|
||||
this.checkmarkCount = checkmarkCount;
|
||||
}
|
||||
|
||||
public void setFilter(HabitMatcher matcher)
|
||||
public synchronized void setFilter(@NonNull HabitMatcher matcher)
|
||||
{
|
||||
if (matcher == null) throw new NullPointerException();
|
||||
filteredHabits = allHabits.getFiltered(matcher);
|
||||
}
|
||||
|
||||
public void setListener(@NonNull Listener listener)
|
||||
public synchronized void setListener(@NonNull Listener listener)
|
||||
{
|
||||
if (listener == null) throw new NullPointerException();
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public void setOrder(HabitList.Order order)
|
||||
public synchronized void setOrder(@NonNull HabitList.Order order)
|
||||
{
|
||||
if (order == null) throw new NullPointerException();
|
||||
allHabits.setOrder(order);
|
||||
filteredHabits.setOrder(order);
|
||||
refreshAllHabits();
|
||||
@@ -198,30 +210,40 @@ public class HabitCardListCache implements CommandRunner.Listener
|
||||
*/
|
||||
public interface Listener
|
||||
{
|
||||
default void onItemChanged(int position) {}
|
||||
default void onItemChanged(int position)
|
||||
{
|
||||
}
|
||||
|
||||
default void onItemInserted(int position) {}
|
||||
default void onItemInserted(int position)
|
||||
{
|
||||
}
|
||||
|
||||
default void onItemMoved(int oldPosition, int newPosition) {}
|
||||
default void onItemMoved(int oldPosition, int newPosition)
|
||||
{
|
||||
}
|
||||
|
||||
default void onItemRemoved(int position) {}
|
||||
default void onItemRemoved(int position)
|
||||
{
|
||||
}
|
||||
|
||||
default void onRefreshFinished() {}
|
||||
default void onRefreshFinished()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class CacheData
|
||||
{
|
||||
@NonNull
|
||||
public HashMap<Long, Habit> id_to_habit;
|
||||
public final HashMap<Long, Habit> id_to_habit;
|
||||
|
||||
@NonNull
|
||||
public List<Habit> habits;
|
||||
public final List<Habit> habits;
|
||||
|
||||
@NonNull
|
||||
public HashMap<Long, int[]> checkmarks;
|
||||
public final HashMap<Long, int[]> checkmarks;
|
||||
|
||||
@NonNull
|
||||
public HashMap<Long, Double> scores;
|
||||
public final HashMap<Long, Double> scores;
|
||||
|
||||
/**
|
||||
* Creates a new CacheData without any content.
|
||||
@@ -234,8 +256,10 @@ public class HabitCardListCache implements CommandRunner.Listener
|
||||
scores = new HashMap<>();
|
||||
}
|
||||
|
||||
public void copyCheckmarksFrom(@NonNull CacheData oldData)
|
||||
public synchronized void copyCheckmarksFrom(@NonNull CacheData oldData)
|
||||
{
|
||||
if (oldData == null) throw new NullPointerException();
|
||||
|
||||
int[] empty = new int[checkmarkCount];
|
||||
|
||||
for (Long id : id_to_habit.keySet())
|
||||
@@ -246,8 +270,10 @@ public class HabitCardListCache implements CommandRunner.Listener
|
||||
}
|
||||
}
|
||||
|
||||
public void copyScoresFrom(@NonNull CacheData oldData)
|
||||
public synchronized void copyScoresFrom(@NonNull CacheData oldData)
|
||||
{
|
||||
if (oldData == null) throw new NullPointerException();
|
||||
|
||||
for (Long id : id_to_habit.keySet())
|
||||
{
|
||||
if (oldData.scores.containsKey(id))
|
||||
@@ -256,10 +282,11 @@ public class HabitCardListCache implements CommandRunner.Listener
|
||||
}
|
||||
}
|
||||
|
||||
public void fetchHabits()
|
||||
public synchronized void fetchHabits()
|
||||
{
|
||||
for (Habit h : filteredHabits)
|
||||
{
|
||||
if (h.getId() == null) continue;
|
||||
habits.add(h);
|
||||
id_to_habit.put(h.getId(), h);
|
||||
}
|
||||
@@ -269,13 +296,14 @@ public class HabitCardListCache implements CommandRunner.Listener
|
||||
private class RefreshTask implements Task
|
||||
{
|
||||
@NonNull
|
||||
private CacheData newData;
|
||||
private final CacheData newData;
|
||||
|
||||
@Nullable
|
||||
private Long targetId;
|
||||
private final Long targetId;
|
||||
|
||||
private boolean isCancelled;
|
||||
|
||||
@Nullable
|
||||
private TaskRunner runner;
|
||||
|
||||
public RefreshTask()
|
||||
@@ -292,13 +320,13 @@ public class HabitCardListCache implements CommandRunner.Listener
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel()
|
||||
public synchronized void cancel()
|
||||
{
|
||||
isCancelled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doInBackground()
|
||||
public synchronized void doInBackground()
|
||||
{
|
||||
newData.fetchHabits();
|
||||
newData.copyScoresFrom(data);
|
||||
@@ -307,7 +335,7 @@ public class HabitCardListCache implements CommandRunner.Listener
|
||||
Timestamp dateTo = DateUtils.getToday();
|
||||
Timestamp dateFrom = dateTo.minus(checkmarkCount - 1);
|
||||
|
||||
runner.publishProgress(this, -1);
|
||||
if (runner != null) runner.publishProgress(this, -1);
|
||||
|
||||
for (int position = 0; position < newData.habits.size(); position++)
|
||||
{
|
||||
@@ -318,35 +346,36 @@ public class HabitCardListCache implements CommandRunner.Listener
|
||||
if (targetId != null && !targetId.equals(id)) continue;
|
||||
|
||||
newData.scores.put(id, habit.getScores().getTodayValue());
|
||||
newData.checkmarks.put(id, habit
|
||||
.getCheckmarks()
|
||||
.getValues(dateFrom, dateTo));
|
||||
newData.checkmarks.put(
|
||||
id,
|
||||
habit.getCheckmarks().getValues(dateFrom, dateTo));
|
||||
|
||||
runner.publishProgress(this, position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttached(@NonNull TaskRunner runner)
|
||||
public synchronized void onAttached(@NonNull TaskRunner runner)
|
||||
{
|
||||
if (runner == null) throw new NullPointerException();
|
||||
this.runner = runner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostExecute()
|
||||
public synchronized void onPostExecute()
|
||||
{
|
||||
currentFetchTask = null;
|
||||
listener.onRefreshFinished();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressUpdate(int currentPosition)
|
||||
public synchronized void onProgressUpdate(int currentPosition)
|
||||
{
|
||||
if (currentPosition < 0) processRemovedHabits();
|
||||
else processPosition(currentPosition);
|
||||
}
|
||||
|
||||
private void performInsert(Habit habit, int position)
|
||||
private synchronized void performInsert(Habit habit, int position)
|
||||
{
|
||||
Long id = habit.getId();
|
||||
data.habits.add(position, habit);
|
||||
@@ -356,14 +385,17 @@ public class HabitCardListCache implements CommandRunner.Listener
|
||||
listener.onItemInserted(position);
|
||||
}
|
||||
|
||||
private void performMove(Habit habit, int fromPosition, int toPosition)
|
||||
private synchronized void performMove(@NonNull Habit habit,
|
||||
int fromPosition,
|
||||
int toPosition)
|
||||
{
|
||||
if(habit == null) throw new NullPointerException();
|
||||
data.habits.remove(fromPosition);
|
||||
data.habits.add(toPosition, habit);
|
||||
listener.onItemMoved(fromPosition, toPosition);
|
||||
}
|
||||
|
||||
private void performUpdate(Long id, int position)
|
||||
private synchronized void performUpdate(long id, int position)
|
||||
{
|
||||
double oldScore = data.scores.get(id);
|
||||
int[] oldCheckmarks = data.checkmarks.get(id);
|
||||
@@ -381,7 +413,7 @@ public class HabitCardListCache implements CommandRunner.Listener
|
||||
listener.onItemChanged(position);
|
||||
}
|
||||
|
||||
private void processPosition(int currentPosition)
|
||||
private synchronized void processPosition(int currentPosition)
|
||||
{
|
||||
Habit habit = newData.habits.get(currentPosition);
|
||||
Long id = habit.getId();
|
||||
@@ -401,7 +433,7 @@ public class HabitCardListCache implements CommandRunner.Listener
|
||||
}
|
||||
}
|
||||
|
||||
private void processRemovedHabits()
|
||||
private synchronized void processRemovedHabits()
|
||||
{
|
||||
Set<Long> before = data.id_to_habit.keySet();
|
||||
Set<Long> after = newData.id_to_habit.keySet();
|
||||
|
||||
Reference in New Issue
Block a user