mirror of https://github.com/iSoron/uhabits.git
parent
8f5f72d9fd
commit
39cec6f11d
@ -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)
|
||||
}
|
||||
}
|
Loading…
Reference in new issue