Convert Preferences

pull/716/head
Quentin Hibon 5 years ago
parent 8f5f72d9fd
commit 39cec6f11d

@ -109,7 +109,7 @@ abstract class BaseWidgetProvider : AppWidgetProvider() {
} }
protected fun getHabitsFromWidgetId(widgetId: Int): List<Habit> { protected fun getHabitsFromWidgetId(widgetId: Int): List<Habit> {
val selectedIds = widgetPrefs.getHabitIdsFromWidgetId(widgetId) val selectedIds = widgetPrefs.getHabitIdsFromWidgetId(widgetId)!!
val selectedHabits = ArrayList<Habit>(selectedIds.size) val selectedHabits = ArrayList<Habit>(selectedIds.size)
for (id in selectedIds) { for (id in selectedIds) {
val h = habits.getById(id) ?: throw HabitNotFoundException() val h = habits.getById(id) ?: throw HabitNotFoundException()

@ -95,7 +95,7 @@ class WidgetUpdater
val modifiedWidgetIds = when (modifiedHabitId) { val modifiedWidgetIds = when (modifiedHabitId) {
null -> widgetIds.toList() null -> widgetIds.toList()
else -> widgetIds.filter { w -> else -> widgetIds.filter { w ->
widgetPrefs.getHabitIdsFromWidgetId(w).contains(modifiedHabitId) widgetPrefs.getHabitIdsFromWidgetId(w)!!.contains(modifiedHabitId)
} }
} }

@ -1,439 +0,0 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.preferences;
import androidx.annotation.*;
import org.isoron.platform.time.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.ui.*;
import org.isoron.uhabits.core.utils.*;
import java.util.*;
public class Preferences
{
@NonNull
private final Storage storage;
@NonNull
private List<Listener> listeners;
@Nullable
private Boolean shouldReverseCheckmarks = null;
public Preferences(@NonNull Storage storage)
{
this.storage = storage;
listeners = new LinkedList<>();
storage.onAttached(this);
}
public void addListener(Listener listener)
{
listeners.add(listener);
}
public Integer getDefaultHabitColor(int fallbackColor)
{
return storage.getInt("pref_default_habit_palette_color",
fallbackColor);
}
public HabitList.Order getDefaultPrimaryOrder()
{
String name = storage.getString("pref_default_order", "BY_POSITION");
try
{
return HabitList.Order.valueOf(name);
}
catch (IllegalArgumentException e)
{
setDefaultPrimaryOrder(HabitList.Order.BY_POSITION);
return HabitList.Order.BY_POSITION;
}
}
public HabitList.Order getDefaultSecondaryOrder() {
String name = storage.getString("pref_default_secondary_order", "BY_NAME_ASC");
try
{
return HabitList.Order.valueOf(name);
}
catch (IllegalArgumentException e)
{
setDefaultSecondaryOrder(HabitList.Order.BY_NAME_ASC);
return HabitList.Order.BY_POSITION;
}
}
public void setDefaultPrimaryOrder(HabitList.Order order)
{
storage.putString("pref_default_order", order.name());
}
public void setDefaultSecondaryOrder(HabitList.Order order)
{
storage.putString("pref_default_secondary_order", order.name());
}
public int getScoreCardSpinnerPosition()
{
return Math.min(4, Math.max(0, storage.getInt("pref_score_view_interval", 1)));
}
public void setScoreCardSpinnerPosition(int position)
{
storage.putInt("pref_score_view_interval", position);
}
public int getBarCardBoolSpinnerPosition()
{
return Math.min(3, Math.max(0, storage.getInt("pref_bar_card_bool_spinner", 0)));
}
public void setBarCardBoolSpinnerPosition(int position)
{
storage.putInt("pref_bar_card_bool_spinner", position);
}
public int getBarCardNumericalSpinnerPosition()
{
return Math.min(4, Math.max(0, storage.getInt("pref_bar_card_numerical_spinner", 0)));
}
public void setBarCardNumericalSpinnerPosition(int position)
{
storage.putInt("pref_bar_card_numerical_spinner", position);
}
public int getLastHintNumber()
{
return storage.getInt("last_hint_number", -1);
}
public Timestamp getLastHintTimestamp()
{
long unixTime = storage.getLong("last_hint_timestamp", -1);
if (unixTime < 0) return null;
else return new Timestamp(unixTime);
}
public boolean getShowArchived()
{
return storage.getBoolean("pref_show_archived", false);
}
public void setShowArchived(boolean showArchived)
{
storage.putBoolean("pref_show_archived", showArchived);
}
public boolean getShowCompleted()
{
return storage.getBoolean("pref_show_completed", true);
}
public void setShowCompleted(boolean showCompleted)
{
storage.putBoolean("pref_show_completed", showCompleted);
}
public long getSnoozeInterval()
{
return Long.parseLong(storage.getString("pref_snooze_interval", "15"));
}
public void setSnoozeInterval(int interval)
{
storage.putString("pref_snooze_interval", String.valueOf(interval));
}
public int getTheme()
{
return storage.getInt("pref_theme", ThemeSwitcher.THEME_AUTOMATIC);
}
public void setTheme(int theme)
{
storage.putInt("pref_theme", theme);
}
public void incrementLaunchCount()
{
storage.putInt("launch_count", getLaunchCount() + 1);
}
public int getLaunchCount()
{
return storage.getInt("launch_count", 0);
}
public boolean isDeveloper()
{
return storage.getBoolean("pref_developer", false);
}
public void setDeveloper(boolean isDeveloper)
{
storage.putBoolean("pref_developer", isDeveloper);
}
public boolean isFirstRun()
{
return storage.getBoolean("pref_first_run", true);
}
public void setFirstRun(boolean isFirstRun)
{
storage.putBoolean("pref_first_run", isFirstRun);
}
public boolean isPureBlackEnabled()
{
return storage.getBoolean("pref_pure_black", false);
}
public void setPureBlackEnabled(boolean enabled)
{
storage.putBoolean("pref_pure_black", enabled);
}
public boolean isShortToggleEnabled()
{
return storage.getBoolean("pref_short_toggle", false);
}
public void setShortToggleEnabled(boolean enabled)
{
storage.putBoolean("pref_short_toggle", enabled);
}
public void removeListener(Listener listener)
{
listeners.remove(listener);
}
public void clear()
{
storage.clear();
}
public void setDefaultHabitColor(int color)
{
storage.putInt("pref_default_habit_palette_color", color);
}
public void setNotificationsSticky(boolean sticky)
{
storage.putBoolean("pref_sticky_notifications", sticky);
for (Listener l : listeners) l.onNotificationsChanged();
}
public void setNotificationsLed(boolean enabled)
{
storage.putBoolean("pref_led_notifications", enabled);
for (Listener l : listeners) l.onNotificationsChanged();
}
public boolean shouldMakeNotificationsSticky()
{
return storage.getBoolean("pref_sticky_notifications", false);
}
public boolean shouldMakeNotificationsLed()
{
return storage.getBoolean("pref_led_notifications", false);
}
public boolean isCheckmarkSequenceReversed()
{
if (shouldReverseCheckmarks == null) shouldReverseCheckmarks =
storage.getBoolean("pref_checkmark_reverse_order", false);
return shouldReverseCheckmarks;
}
public void setCheckmarkSequenceReversed(boolean reverse)
{
shouldReverseCheckmarks = reverse;
storage.putBoolean("pref_checkmark_reverse_order", reverse);
for (Listener l : listeners) l.onCheckmarkSequenceChanged();
}
public void updateLastHint(int number, Timestamp timestamp)
{
storage.putInt("last_hint_number", number);
storage.putLong("last_hint_timestamp", timestamp.getUnixTime());
}
public int getLastAppVersion()
{
return storage.getInt("last_version", 0);
}
public void setLastAppVersion(int version)
{
storage.putInt("last_version", version);
}
public int getWidgetOpacity()
{
return Integer.parseInt(storage.getString("pref_widget_opacity", "255"));
}
public void setWidgetOpacity(int value)
{
storage.putString("pref_widget_opacity", Integer.toString(value));
}
public boolean isSkipEnabled()
{
return storage.getBoolean("pref_skip_enabled", false);
}
public void setSkipEnabled(boolean value)
{
storage.putBoolean("pref_skip_enabled", value);
}
public String getSyncBaseURL()
{
return storage.getString("pref_sync_base_url", "");
}
public String getSyncKey()
{
return storage.getString("pref_sync_key", "");
}
public String getEncryptionKey()
{
return storage.getString("pref_encryption_key", "");
}
public boolean isSyncEnabled()
{
return storage.getBoolean("pref_sync_enabled", false);
}
public void enableSync(String syncKey, String encKey)
{
storage.putBoolean("pref_sync_enabled", true);
storage.putString("pref_sync_key", syncKey);
storage.putString("pref_encryption_key", encKey);
for (Listener l : listeners) l.onSyncEnabled();
}
public void disableSync()
{
storage.putBoolean("pref_sync_enabled", false);
storage.putString("pref_sync_key", "");
storage.putString("pref_encryption_key", "");
}
public boolean areQuestionMarksEnabled()
{
return storage.getBoolean("pref_unknown_enabled", false);
}
/**
* @return An integer representing the first day of the week. Sunday
* corresponds to 1, Monday to 2, and so on, until Saturday, which is
* represented by 7. By default, this is based on the current system locale,
* unless the user changed this in the settings.
*/
@Deprecated()
public int getFirstWeekdayInt()
{
String weekday = storage.getString("pref_first_weekday", "");
if (weekday.isEmpty()) return DateUtils.getFirstWeekdayNumberAccordingToLocale();
return Integer.parseInt(weekday);
}
public DayOfWeek getFirstWeekday()
{
int weekday = Integer.parseInt(storage.getString("pref_first_weekday", "-1"));
if (weekday < 0) weekday = DateUtils.getFirstWeekdayNumberAccordingToLocale();
switch (weekday) {
case 1: return DayOfWeek.SUNDAY;
case 2: return DayOfWeek.MONDAY;
case 3: return DayOfWeek.TUESDAY;
case 4: return DayOfWeek.WEDNESDAY;
case 5: return DayOfWeek.THURSDAY;
case 6: return DayOfWeek.FRIDAY;
case 7: return DayOfWeek.SATURDAY;
default: throw new IllegalArgumentException();
}
}
public interface Listener
{
default void onCheckmarkSequenceChanged()
{
}
default void onNotificationsChanged()
{
}
default void onSyncEnabled()
{
}
}
public interface Storage
{
void clear();
boolean getBoolean(String key, boolean defValue);
int getInt(String key, int defValue);
long getLong(String key, long defValue);
String getString(String key, String defValue);
void onAttached(Preferences preferences);
void putBoolean(String key, boolean value);
void putInt(String key, int value);
void putLong(String key, long value);
void putString(String key, String value);
void remove(String key);
default void putLongArray(String key, long[] values)
{
putString(key, StringUtils.joinLongs(values));
}
default long[] getLongArray(String key, long[] defValue)
{
String string = getString(key, "");
if (string.isEmpty()) return defValue;
else return StringUtils.splitLongs(string);
}
}
}

@ -0,0 +1,294 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.preferences
import org.isoron.platform.time.DayOfWeek
import org.isoron.uhabits.core.models.HabitList
import org.isoron.uhabits.core.models.Timestamp
import org.isoron.uhabits.core.ui.ThemeSwitcher
import org.isoron.uhabits.core.utils.DateUtils.Companion.getFirstWeekdayNumberAccordingToLocale
import org.isoron.uhabits.core.utils.StringUtils.Companion.joinLongs
import org.isoron.uhabits.core.utils.StringUtils.Companion.splitLongs
import java.util.LinkedList
import kotlin.math.max
import kotlin.math.min
class Preferences(private val storage: Storage) {
private val listeners: MutableList<Listener>
private var shouldReverseCheckmarks: Boolean? = null
fun addListener(listener: Listener) {
listeners.add(listener)
}
fun getDefaultHabitColor(fallbackColor: Int): Int {
return storage.getInt(
"pref_default_habit_palette_color",
fallbackColor
)
}
var defaultPrimaryOrder: HabitList.Order
get() {
val name = storage.getString("pref_default_order", "BY_POSITION")
return try {
HabitList.Order.valueOf(name)
} catch (e: IllegalArgumentException) {
defaultPrimaryOrder = HabitList.Order.BY_POSITION
HabitList.Order.BY_POSITION
}
}
set(order) {
storage.putString("pref_default_order", order.name)
}
var defaultSecondaryOrder: HabitList.Order
get() {
val name = storage.getString("pref_default_secondary_order", "BY_NAME_ASC")
return try {
HabitList.Order.valueOf(name)
} catch (e: IllegalArgumentException) {
defaultSecondaryOrder = HabitList.Order.BY_NAME_ASC
HabitList.Order.BY_POSITION
}
}
set(order) {
storage.putString("pref_default_secondary_order", order.name)
}
var scoreCardSpinnerPosition: Int
get() = min(4, max(0, storage.getInt("pref_score_view_interval", 1)))
set(position) {
storage.putInt("pref_score_view_interval", position)
}
var barCardBoolSpinnerPosition: Int
get() = min(3, max(0, storage.getInt("pref_bar_card_bool_spinner", 0)))
set(position) {
storage.putInt("pref_bar_card_bool_spinner", position)
}
var barCardNumericalSpinnerPosition: Int
get() = min(4, max(0, storage.getInt("pref_bar_card_numerical_spinner", 0)))
set(position) {
storage.putInt("pref_bar_card_numerical_spinner", position)
}
val lastHintNumber: Int
get() = storage.getInt("last_hint_number", -1)
val lastHintTimestamp: Timestamp?
get() {
val unixTime = storage.getLong("last_hint_timestamp", -1)
return if (unixTime < 0) null else Timestamp(unixTime)
}
var showArchived: Boolean
get() = storage.getBoolean("pref_show_archived", false)
set(showArchived) {
storage.putBoolean("pref_show_archived", showArchived)
}
var showCompleted: Boolean
get() = storage.getBoolean("pref_show_completed", true)
set(showCompleted) {
storage.putBoolean("pref_show_completed", showCompleted)
}
val snoozeInterval: Long
get() = storage.getString("pref_snooze_interval", "15").toLong()
fun setSnoozeInterval(interval: Int) {
storage.putString("pref_snooze_interval", interval.toString())
}
var theme: Int
get() = storage.getInt("pref_theme", ThemeSwitcher.THEME_AUTOMATIC)
set(theme) {
storage.putInt("pref_theme", theme)
}
fun incrementLaunchCount() {
storage.putInt("launch_count", launchCount + 1)
}
val launchCount: Int
get() = storage.getInt("launch_count", 0)
var isDeveloper: Boolean
get() = storage.getBoolean("pref_developer", false)
set(isDeveloper) {
storage.putBoolean("pref_developer", isDeveloper)
}
var isFirstRun: Boolean
get() = storage.getBoolean("pref_first_run", true)
set(isFirstRun) {
storage.putBoolean("pref_first_run", isFirstRun)
}
var isPureBlackEnabled: Boolean
get() = storage.getBoolean("pref_pure_black", false)
set(enabled) {
storage.putBoolean("pref_pure_black", enabled)
}
var isShortToggleEnabled: Boolean
get() = storage.getBoolean("pref_short_toggle", false)
set(enabled) {
storage.putBoolean("pref_short_toggle", enabled)
}
fun removeListener(listener: Listener) {
listeners.remove(listener)
}
fun clear() {
storage.clear()
}
fun setDefaultHabitColor(color: Int) {
storage.putInt("pref_default_habit_palette_color", color)
}
fun setNotificationsSticky(sticky: Boolean) {
storage.putBoolean("pref_sticky_notifications", sticky)
for (l in listeners) l.onNotificationsChanged()
}
fun setNotificationsLed(enabled: Boolean) {
storage.putBoolean("pref_led_notifications", enabled)
for (l in listeners) l.onNotificationsChanged()
}
fun shouldMakeNotificationsSticky(): Boolean {
return storage.getBoolean("pref_sticky_notifications", false)
}
fun shouldMakeNotificationsLed(): Boolean {
return storage.getBoolean("pref_led_notifications", false)
}
var isCheckmarkSequenceReversed: Boolean
get() {
if (shouldReverseCheckmarks == null) shouldReverseCheckmarks =
storage.getBoolean("pref_checkmark_reverse_order", false)
return shouldReverseCheckmarks!!
}
set(reverse) {
shouldReverseCheckmarks = reverse
storage.putBoolean("pref_checkmark_reverse_order", reverse)
for (l in listeners) l.onCheckmarkSequenceChanged()
}
fun updateLastHint(number: Int, timestamp: Timestamp) {
storage.putInt("last_hint_number", number)
storage.putLong("last_hint_timestamp", timestamp.unixTime)
}
var lastAppVersion: Int
get() = storage.getInt("last_version", 0)
set(version) {
storage.putInt("last_version", version)
}
var widgetOpacity: Int
get() = storage.getString("pref_widget_opacity", "255").toInt()
set(value) {
storage.putString("pref_widget_opacity", value.toString())
}
var isSkipEnabled: Boolean
get() = storage.getBoolean("pref_skip_enabled", false)
set(value) {
storage.putBoolean("pref_skip_enabled", value)
}
val syncBaseURL: String
get() = storage.getString("pref_sync_base_url", "")
val syncKey: String
get() = storage.getString("pref_sync_key", "")
val encryptionKey: String
get() = storage.getString("pref_encryption_key", "")
val isSyncEnabled: Boolean
get() = storage.getBoolean("pref_sync_enabled", false)
fun enableSync(syncKey: String, encKey: String) {
storage.putBoolean("pref_sync_enabled", true)
storage.putString("pref_sync_key", syncKey)
storage.putString("pref_encryption_key", encKey)
for (l in listeners) l.onSyncEnabled()
}
fun disableSync() {
storage.putBoolean("pref_sync_enabled", false)
storage.putString("pref_sync_key", "")
storage.putString("pref_encryption_key", "")
}
fun areQuestionMarksEnabled(): Boolean {
return storage.getBoolean("pref_unknown_enabled", false)
}
/**
* @return An integer representing the first day of the week. Sunday
* corresponds to 1, Monday to 2, and so on, until Saturday, which is
* represented by 7. By default, this is based on the current system locale,
* unless the user changed this in the settings.
*/
@get:Deprecated("")
val firstWeekdayInt: Int
get() {
val weekday = storage.getString("pref_first_weekday", "")
return if (weekday.isEmpty()) getFirstWeekdayNumberAccordingToLocale() else weekday.toInt()
}
val firstWeekday: DayOfWeek
get() {
var weekday = storage.getString("pref_first_weekday", "-1").toInt()
if (weekday < 0) weekday = getFirstWeekdayNumberAccordingToLocale()
return when (weekday) {
1 -> DayOfWeek.SUNDAY
2 -> DayOfWeek.MONDAY
3 -> DayOfWeek.TUESDAY
4 -> DayOfWeek.WEDNESDAY
5 -> DayOfWeek.THURSDAY
6 -> DayOfWeek.FRIDAY
7 -> DayOfWeek.SATURDAY
else -> throw IllegalArgumentException()
}
}
interface Listener {
fun onCheckmarkSequenceChanged() {}
fun onNotificationsChanged() {}
fun onSyncEnabled() {}
}
interface Storage {
fun clear()
fun getBoolean(key: String, defValue: Boolean): Boolean
fun getInt(key: String, defValue: Int): Int
fun getLong(key: String, defValue: Long): Long
fun getString(key: String, defValue: String): String
fun onAttached(preferences: Preferences)
fun putBoolean(key: String, value: Boolean)
fun putInt(key: String, value: Int)
fun putLong(key: String, value: Long)
fun putString(key: String, value: String)
fun remove(key: String)
fun putLongArray(key: String, values: LongArray) {
putString(key, joinLongs(values))
}
fun getLongArray(key: String, defValue: LongArray): LongArray? {
val string = getString(key, "")
return if (string.isEmpty()) defValue else splitLongs(
string
)
}
}
init {
listeners = LinkedList()
storage.onAttached(this)
}
}

@ -1,134 +0,0 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.preferences;
import androidx.annotation.*;
import java.io.*;
import java.util.*;
public class PropertiesStorage implements Preferences.Storage
{
@NonNull
private final Properties props;
@NonNull
private File file;
public PropertiesStorage(@NonNull File file)
{
try
{
this.file = file;
props = new Properties();
props.load(new FileInputStream(file));
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
@Override
public void clear()
{
for(String key : props.stringPropertyNames()) props.remove(key);
flush();
}
@Override
public boolean getBoolean(String key, boolean defValue)
{
String value = props.getProperty(key, Boolean.toString(defValue));
return Boolean.parseBoolean(value);
}
@Override
public int getInt(String key, int defValue)
{
String value = props.getProperty(key, Integer.toString(defValue));
return Integer.parseInt(value);
}
@Override
public long getLong(String key, long defValue)
{
String value = props.getProperty(key, Long.toString(defValue));
return Long.parseLong(value);
}
@Override
public String getString(String key, String defValue)
{
return props.getProperty(key, defValue);
}
@Override
public void onAttached(Preferences preferences)
{
// nop
}
@Override
public void putBoolean(String key, boolean value)
{
props.setProperty(key, Boolean.toString(value));
}
@Override
public void putInt(String key, int value)
{
props.setProperty(key, Integer.toString(value));
flush();
}
private void flush()
{
try
{
props.store(new FileOutputStream(file), "");
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
@Override
public void putLong(String key, long value)
{
props.setProperty(key, Long.toString(value));
flush();
}
@Override
public void putString(String key, String value)
{
props.setProperty(key, value);
flush();
}
@Override
public void remove(String key)
{
props.remove(key);
flush();
}
}

@ -0,0 +1,99 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.preferences
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
import java.util.Properties
class PropertiesStorage(file: File) : Preferences.Storage {
private var props: Properties
private val file: File
override fun clear() {
for (key in props.stringPropertyNames()) props.remove(key)
flush()
}
override fun getBoolean(key: String, defValue: Boolean): Boolean {
val value = props.getProperty(key, java.lang.Boolean.toString(defValue))
return java.lang.Boolean.parseBoolean(value)
}
override fun getInt(key: String, defValue: Int): Int {
val value = props.getProperty(key, defValue.toString())
return value.toInt()
}
override fun getLong(key: String, defValue: Long): Long {
val value = props.getProperty(key, defValue.toString())
return value.toLong()
}
override fun getString(key: String, defValue: String): String {
return props.getProperty(key, defValue)
}
override fun onAttached(preferences: Preferences) {
// nop
}
override fun putBoolean(key: String, value: Boolean) {
props.setProperty(key, java.lang.Boolean.toString(value))
}
override fun putInt(key: String, value: Int) {
props.setProperty(key, value.toString())
flush()
}
private fun flush() {
try {
props.store(FileOutputStream(file), "")
} catch (e: IOException) {
throw RuntimeException(e)
}
}
override fun putLong(key: String, value: Long) {
props.setProperty(key, value.toString())
flush()
}
override fun putString(key: String, value: String) {
props.setProperty(key, value)
flush()
}
override fun remove(key: String) {
props.remove(key)
flush()
}
init {
try {
this.file = file
props = Properties()
props.load(FileInputStream(file))
} catch (e: IOException) {
throw RuntimeException(e)
}
}
}

@ -1,82 +0,0 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.preferences;
import org.isoron.uhabits.core.AppScope;
import javax.inject.Inject;
@AppScope
public class WidgetPreferences {
private Preferences.Storage storage;
@Inject
public WidgetPreferences(Preferences.Storage storage) {
this.storage = storage;
}
public void addWidget(int widgetId, long[] habitIds) {
storage.putLongArray(getHabitIdKey(widgetId), habitIds);
}
public long[] getHabitIdsFromWidgetId(int widgetId) {
long[] habitIds;
String habitIdKey = getHabitIdKey(widgetId);
try {
habitIds = storage.getLongArray(habitIdKey, new long[]{-1});
} catch (ClassCastException e) {
// Up to Loop 1.7.11, this preference was not an array, but a single
// long. Trying to read the old preference causes a cast exception.
habitIds = new long[1];
habitIds[0] = storage.getLong(habitIdKey, -1);
storage.putLongArray(habitIdKey, habitIds);
}
return habitIds;
}
public void removeWidget(int id) {
String habitIdKey = getHabitIdKey(id);
storage.remove(habitIdKey);
}
public long getSnoozeTime(long id)
{
return storage.getLong(getSnoozeKey(id), 0);
}
private String getHabitIdKey(int id) {
return String.format("widget-%06d-habit", id);
}
private String getSnoozeKey(long id)
{
return String.format("snooze-%06d", id);
}
public void removeSnoozeTime(long id)
{
storage.putLong(getSnoozeKey(id), 0);
}
public void setSnoozeTime(Long id, long time)
{
storage.putLong(getSnoozeKey(id), time);
}
}

@ -0,0 +1,69 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.preferences
import org.isoron.uhabits.core.AppScope
import javax.inject.Inject
@AppScope
class WidgetPreferences @Inject constructor(private val storage: Preferences.Storage) {
fun addWidget(widgetId: Int, habitIds: LongArray) {
storage.putLongArray(getHabitIdKey(widgetId), habitIds)
}
fun getHabitIdsFromWidgetId(widgetId: Int): LongArray? {
var habitIds: LongArray?
val habitIdKey = getHabitIdKey(widgetId)
try {
habitIds = storage.getLongArray(habitIdKey, longArrayOf(-1))
} catch (e: ClassCastException) {
// Up to Loop 1.7.11, this preference was not an array, but a single
// long. Trying to read the old preference causes a cast exception.
habitIds = LongArray(1)
habitIds[0] = storage.getLong(habitIdKey, -1)
storage.putLongArray(habitIdKey, habitIds)
}
return habitIds
}
fun removeWidget(id: Int) {
val habitIdKey = getHabitIdKey(id)
storage.remove(habitIdKey)
}
fun getSnoozeTime(id: Long): Long {
return storage.getLong(getSnoozeKey(id), 0)
}
private fun getHabitIdKey(id: Int): String {
return String.format("widget-%06d-habit", id)
}
private fun getSnoozeKey(id: Long): String {
return String.format("snooze-%06d", id)
}
fun removeSnoozeTime(id: Long) {
storage.putLong(getSnoozeKey(id), 0)
}
fun setSnoozeTime(id: Long, time: Long) {
storage.putLong(getSnoozeKey(id), time)
}
}

@ -129,7 +129,7 @@ class ReminderScheduler @Inject constructor(
fun snoozeReminder(habit: Habit, minutes: Long) { fun snoozeReminder(habit: Habit, minutes: Long) {
val now = applyTimezone(getLocalTime()) val now = applyTimezone(getLocalTime())
val snoozedUntil = now + minutes * 60 * 1000 val snoozedUntil = now + minutes * 60 * 1000
widgetPreferences.setSnoozeTime(habit.id, snoozedUntil) widgetPreferences.setSnoozeTime(habit.id!!, snoozedUntil)
schedule(habit) schedule(habit)
} }

@ -51,6 +51,6 @@ class HintList(private val prefs: Preferences, private val hints: Array<String>)
fun shouldShow(): Boolean { fun shouldShow(): Boolean {
val today = getToday() val today = getToday()
val lastHintTimestamp = prefs.lastHintTimestamp val lastHintTimestamp = prefs.lastHintTimestamp
return lastHintTimestamp.isOlderThan(today) return lastHintTimestamp?.isOlderThan(today) == true
} }
} }

Loading…
Cancel
Save