/**
* Copyright (c) 2013, Redsolution LTD. All rights reserved.
*
* This file is part of Xabber project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License, Version 3.
*
* Xabber 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 com.xabber.android.data;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.net.Uri;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import com.xabber.android.BuildConfig;
import com.xabber.android.R;
import com.xabber.android.data.account.AccountManager;
import com.xabber.android.data.account.StatusMode;
import com.xabber.android.data.connection.WakeLockManager;
import com.xabber.android.data.entity.AccountJid;
import com.xabber.android.data.extension.attention.AttentionManager;
import com.xabber.android.data.extension.carbons.CarbonManager;
import com.xabber.android.data.extension.otr.OTRManager;
import com.xabber.android.data.log.LogManager;
import com.xabber.android.data.message.MessageManager;
import com.xabber.android.data.notification.NotificationManager;
import com.xabber.android.data.roster.AbstractContact;
import com.xabber.android.service.XabberService;
import com.xabber.android.ui.adapter.ComparatorByName;
import com.xabber.android.ui.adapter.ComparatorByStatus;
import com.xabber.android.ui.color.ColorManager;
import com.xabber.android.utils.Emoticons;
import java.util.Collections;
import java.util.Comparator;
import java.util.Map;
import java.util.regex.Pattern;
/**
* Manage operations with common settings.
*
* @author alexander.ivanov
*/
public class SettingsManager implements OnInitializedListener,
OnMigrationListener, OnSharedPreferenceChangeListener {
private static SettingsManager instance;
private SettingsManager() {
getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
public static SettingsManager getInstance() {
if (instance == null) {
instance = new SettingsManager();
}
return instance;
}
private static SharedPreferences getSharedPreferences() {
return PreferenceManager.getDefaultSharedPreferences(Application
.getInstance());
}
private static int getInt(int key, int def) {
String value = getString(key, def);
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
return Integer.parseInt(Application.getInstance().getString(def));
}
}
private static boolean getBoolean(int key, boolean def) {
return getSharedPreferences().getBoolean(
Application.getInstance().getString(key), def);
}
private static boolean getBoolean(int key, int def) {
return getBoolean(key, Application.getInstance().getResources()
.getBoolean(def));
}
private static void setBoolean(int key, boolean value) {
Editor editor = getSharedPreferences().edit();
editor.putBoolean(Application.getInstance().getString(key), value);
editor.commit();
}
private static String getString(int key, String def) {
return getSharedPreferences().getString(
Application.getInstance().getString(key), def);
}
private static String getString(int key, int def) {
return getString(key, Application.getInstance().getString(def));
}
private static void setString(int key, String value) {
Editor editor = getSharedPreferences().edit();
editor.putString(Application.getInstance().getString(key), value);
editor.commit();
}
/**
* @param key
* @param defaultUri
* @return Sound uri. Sets defaulUri if value is default.
*/
private static Uri getSound(int key, Uri defaultUri, int defaultResource) {
String defaultValue = Application.getInstance().getString(
defaultResource);
String value = getString(key, defaultValue);
if (TextUtils.isEmpty(value))
return null;
if (defaultValue.equals(value)) {
setString(key, defaultUri.toString());
return defaultUri;
}
return Uri.parse(value);
}
public static boolean contactsShowAvatars() {
return getBoolean(R.string.contacts_show_avatars_key,
R.bool.contacts_show_avatars_default);
}
public static boolean contactsShowOffline() {
return getBoolean(R.string.contacts_show_offline_key,
R.bool.contacts_show_offline_default);
}
public static void setContactsShowOffline(boolean show) {
setBoolean(R.string.contacts_show_offline_key, show);
}
public static boolean contactsShowGroups() {
return getBoolean(R.string.contacts_show_groups_key,
R.bool.contacts_show_groups_default);
}
public static boolean contactsShowEmptyGroups() {
return getBoolean(R.string.contacts_show_empty_groups_key,
R.bool.contacts_show_empty_groups_default);
}
public static boolean contactsShowActiveChats() {
return getBoolean(R.string.contacts_show_active_chats_key,
R.bool.contacts_show_active_chats_default);
}
public static boolean contactsStayActiveChats() {
return getBoolean(R.string.contacts_stay_active_chats_key,
R.bool.contacts_stay_active_chats_default);
}
public static boolean contactsShowAccounts() {
return getBoolean(R.string.contacts_show_accounts_key,
R.bool.contacts_show_accounts_default);
}
public static Comparator<AbstractContact> contactsOrder() {
String value = getString(R.string.contacts_order_key,
R.string.contacts_order_default);
if (Application.getInstance()
.getString(R.string.contacts_order_alphabet_value)
.equals(value))
return ComparatorByName.COMPARATOR_BY_NAME;
else if (Application.getInstance()
.getString(R.string.contacts_order_status_value).equals(value))
return ComparatorByStatus.COMPARATOR_BY_STATUS;
else
throw new IllegalStateException();
}
public static boolean contactsShowPanel() {
return getBoolean(R.string.contacts_show_panel_key,
R.bool.contacts_show_panel_default);
}
public static boolean contactsEnableShowAccounts() {
return getBoolean(R.string.contacts_enable_show_accounts_key,
R.bool.contacts_enable_show_accounts_default);
}
/**
* DON`T USE THIS METHOD DIRECTLY.
* <p/>
* Use {@link AccountManager#getSelectedAccount()} instead.
*
* @return
*/
public static String contactsSelectedAccount() {
return getString(R.string.contacts_selected_account_key, "");
}
public static void setContactsSelectedAccount(AccountJid account) {
String value;
if (account == null) {
value = "";
} else {
value = account.toString();
}
setString(R.string.contacts_selected_account_key, value);
}
public static void enableContactsShowAccount() {
setBoolean(R.string.contacts_enable_show_accounts_key, false);
setBoolean(R.string.contacts_show_accounts_key, true);
}
/**
* Gets event sound. It will save DEFAULT_NOTIFICATION_URI if value is
* default.
*
* @return {@link Uri} or <code>null</code>.
*/
public static Uri eventsSound() {
return getSound(R.string.events_sound_key,
Settings.System.DEFAULT_NOTIFICATION_URI,
R.string.events_sound_default);
}
public static boolean eventsVibro() {
return getBoolean(R.string.events_vibro_key,
R.bool.events_vibro_default);
}
public static boolean eventsSuppress100() {
return getBoolean(R.string.chat_events_suppress_100_key,
R.bool.chat_events_suppress_100_default);
}
public static boolean eventsIgnoreSystemVibro() {
return getBoolean(R.string.events_ignore_system_vibro_key,
R.bool.events_ignore_system_vibro_default);
}
public static boolean eventsLightning() {
return getBoolean(R.string.events_lightning_key,
R.bool.events_lightning_default);
}
public static boolean eventsPersistent() {
return getBoolean(R.string.events_persistent_key,
R.bool.events_persistent_default);
}
public static boolean eventsShowText() {
return getBoolean(R.string.events_show_text_key,
R.bool.events_show_text_default);
}
public static EventsMessage eventsMessage() {
String value = getString(R.string.events_message_key,
R.string.events_message_default);
if (Application.getInstance()
.getString(R.string.events_message_none_value).equals(value))
return EventsMessage.none;
else if (Application.getInstance()
.getString(R.string.events_message_chat_value).equals(value))
return EventsMessage.chat;
else if (Application.getInstance()
.getString(R.string.events_message_chat_and_muc_value)
.equals(value))
return EventsMessage.chatAndMuc;
else
throw new IllegalStateException();
}
public static boolean eventsVisibleChat() {
return getBoolean(R.string.events_visible_chat_key,
R.bool.events_visible_chat_default);
}
public static boolean eventsFirstOnly() {
return getBoolean(R.string.events_first_only_key,
R.bool.events_first_only_default);
}
public static boolean chatsShowAvatars() {
return getBoolean(R.string.chats_show_avatars_key,
R.bool.chats_show_avatars_default);
}
public static boolean chatsSendByEnter() {
return getBoolean(R.string.chats_send_by_enter_key,
R.bool.chats_send_by_enter_default);
}
public static ChatsShowStatusChange chatsShowStatusChange() {
String value = getString(R.string.chats_show_status_change_key,
R.string.chats_show_status_change_default);
if (Application.getInstance()
.getString(R.string.chats_show_status_change_always_value)
.equals(value))
return ChatsShowStatusChange.always;
else if (Application.getInstance()
.getString(R.string.chats_show_status_change_muc_value)
.equals(value))
return ChatsShowStatusChange.muc;
else if (Application.getInstance()
.getString(R.string.chats_show_status_change_never_value)
.equals(value))
return ChatsShowStatusChange.never;
else
throw new IllegalStateException();
}
public static ChatsHideKeyboard chatsHideKeyboard() {
String value = getString(R.string.chats_hide_keyboard_key,
R.string.chats_hide_keyboard_default);
if (Application.getInstance()
.getString(R.string.chats_hide_keyboard_always_value)
.equals(value))
return ChatsHideKeyboard.always;
else if (Application.getInstance()
.getString(R.string.chats_hide_keyboard_landscape_value)
.equals(value))
return ChatsHideKeyboard.landscape;
else if (Application.getInstance()
.getString(R.string.chats_hide_keyboard_never_value)
.equals(value))
return ChatsHideKeyboard.never;
else
throw new IllegalStateException();
}
public static boolean chatsShowBackground() {
return getBoolean(R.string.chats_show_background_key, R.bool.chats_show_background_default);
}
public static int chatsAppearanceStyle() {
String value = getString(R.string.chats_font_size_key,
R.string.chats_font_size_default);
if (Application.getInstance()
.getString(R.string.chats_font_size_small_value).equals(value))
return R.style.ChatText_Small;
else if (Application.getInstance()
.getString(R.string.chats_font_size_normal_value).equals(value))
return R.style.ChatText_Normal;
else if (Application.getInstance()
.getString(R.string.chats_font_size_large_value).equals(value))
return R.style.ChatText_Large;
else if (Application.getInstance()
.getString(R.string.chats_font_size_xlarge_value).equals(value))
return R.style.ChatText_XLarge;
else
throw new IllegalStateException();
}
public static boolean chatsStateNotification() {
return getBoolean(R.string.chats_state_notification_key,
R.bool.chats_state_notification_default);
}
public static boolean chatsAttention() {
return getBoolean(R.string.chats_attention_key,
R.bool.chats_attention_default);
}
/**
* Gets event sound. It will save DEFAULT_NOTIFICATION_URI if value is
* default.
*
* @return {@link Uri} or <code>null</code>.
*/
public static Uri chatsAttentionSound() {
return getSound(R.string.chats_attention_sound_key,
Settings.System.DEFAULT_RINGTONE_URI,
R.string.chats_attention_sound_default);
}
public static int connectionGoAway() {
return getInt(R.string.connection_go_away_key,
R.string.connection_go_away_default);
}
public static int connectionGoXa() {
return getInt(R.string.connection_go_xa_key,
R.string.connection_go_xa_default);
}
public static boolean connectionWifiLock() {
return getBoolean(R.string.connection_wifi_lock_key,
R.bool.connection_wifi_lock_default);
}
public static boolean connectionWakeLock() {
return getBoolean(R.string.connection_wake_lock_key,
R.bool.connection_wake_lock_default);
}
public static boolean connectionStartAtBoot() {
return getBoolean(R.string.connection_start_at_boot_key,
R.bool.connection_start_at_boot_default);
}
public static void setConnectionStartAtBoot(boolean value) {
setBoolean(R.string.connection_start_at_boot_key, value);
}
public static boolean connectionLoadVCard() {
return getBoolean(R.string.connection_load_vcard_key,
R.bool.connection_load_vcard_default);
}
public static boolean connectionLoadImages() {
return getBoolean(R.string.connection_load_images_key,
R.bool.connection_load_images_default);
}
public static boolean connectionUseCarbons() {
return getBoolean(R.string.connection_use_carbons_key,
R.bool.connection_use_carbons_default);
}
public static DnsResolverType connectionDnsResolver() {
String value = getString(R.string.connection_dns_resolver_type_key,
R.string.connection_dns_resolver_type_default);
return getDnsResolverType(value);
}
@NonNull
public static DnsResolverType getDnsResolverType(String value) {
if (Application.getInstance().getString(R.string.connection_dns_resolver_type_dns_java_resolver_value).equals(value)) {
return DnsResolverType.dnsJavaResolver;
} else if (Application.getInstance().getString(R.string.connection_dns_resolver_type_mini_dns_resolver_value).equals(value)) {
return DnsResolverType.miniDnsResolver;
} else {
throw new IllegalStateException("Unknown preference value for DNS resolver type");
}
}
public static boolean connectionUsePlainTextAuth() {
return getBoolean(R.string.connection_use_plain_text_auth_key,
R.bool.connection_use_plain_text_auth_default);
}
public static boolean connectionAdjustPriority() {
return getBoolean(R.string.connection_adjust_priority_key,
R.bool.connection_adjust_priority_default);
}
public static int connectionPriorityAvailable() {
return getInt(R.string.connection_priority_available_key,
R.string.connection_priority_available_default);
}
public static int connectionPriorityAway() {
return getInt(R.string.connection_priority_away_key,
R.string.connection_priority_away_default);
}
public static int connectionPriorityChat() {
return getInt(R.string.connection_priority_chat_key,
R.string.connection_priority_chat_default);
}
public static int connectionPriorityDnd() {
return getInt(R.string.connection_priority_dnd_key,
R.string.connection_priority_dnd_default);
}
public static int connectionPriorityXa() {
return getInt(R.string.connection_priority_xa_key,
R.string.connection_priority_xa_default);
}
public static boolean debugLog() {
return getBoolean(R.string.debug_log_key, R.bool.debug_log_default);
}
public static boolean fileLog() {
return getBoolean(R.string.debug_file_log_key, R.bool.debug_file_log_default);
}
public static boolean showConnectionErrors() {
return getBoolean(R.string.debug_connection_errors_key, R.bool.debug_connection_errors_default);
}
public static boolean sendCrashReports() {
return getBoolean(R.string.debug_crash_reports_key, R.bool.debug_crash_reports_default);
}
public static boolean isCrashReportsSupported() {
return BuildConfig.FLAVOR.equals("beta")
|| BuildConfig.FLAVOR.equals("vip")
|| BuildConfig.FLAVOR.equals("prod");
}
public static boolean isCrashReportsDialogShown() {
return getBoolean(R.string.debug_crash_reports_dialog_key, false);
}
public static void setCrashReportsDialogShown() {
setBoolean(R.string.debug_crash_reports_dialog_key, true);
}
public static InterfaceTheme interfaceTheme() {
String value = getString(R.string.interface_theme_key, R.string.interface_theme_default);
if (Application.getInstance().getString(R.string.interface_theme_dark_value).equals(value)) {
return InterfaceTheme.dark;
} else if (Application.getInstance().getString(R.string.interface_theme_light_value).equals(value)) {
return InterfaceTheme.light;
} else if (Application.getInstance().getString(R.string.interface_theme_normal_value).equals(value)) {
return InterfaceTheme.light;
} else {
throw new IllegalStateException();
}
}
public static Map<Pattern, Integer> interfaceSmiles() {
String value = getString(R.string.interface_smiles_key, R.string.interface_smiles_default);
if (Application.getInstance().getString(R.string.interface_smiles_none_value).equals(value)) {
return Collections.unmodifiableMap(Emoticons.NONE_EMOTICONS);
} else if (Application.getInstance().getString(R.string.interface_smiles_android_value).equals(value)) {
return Collections.unmodifiableMap(Emoticons.ANDROID_EMOTICONS);
} else {
throw new IllegalStateException();
}
}
public static boolean securityCheckCertificate() {
return getBoolean(R.string.security_check_certificate_key,
R.bool.security_check_certificate_default);
}
public static SecurityOtrMode securityOtrMode() {
String value = getString(R.string.security_otr_mode_key,
R.string.security_otr_mode_default);
if (Application.getInstance()
.getString(R.string.security_otr_mode_disabled_value)
.equals(value))
return SecurityOtrMode.disabled;
else if (Application.getInstance()
.getString(R.string.security_otr_mode_manual_value)
.equals(value))
return SecurityOtrMode.manual;
else if (Application.getInstance()
.getString(R.string.security_otr_mode_auto_value).equals(value))
return SecurityOtrMode.auto;
else if (Application.getInstance()
.getString(R.string.security_otr_mode_required_value)
.equals(value))
return SecurityOtrMode.required;
else
throw new IllegalStateException();
}
public static boolean securityOtrHistory() {
return getBoolean(R.string.security_otr_history_key,
R.bool.security_otr_history_default);
}
public static int bootCount() {
return getSharedPreferences()
.getInt(Application.getInstance().getString(
R.string.boot_count_key), 0);
}
public static void incrementBootCount() {
Editor editor = getSharedPreferences().edit();
editor.putInt(
Application.getInstance().getString(R.string.boot_count_key),
bootCount() + 1);
editor.commit();
}
public static boolean startAtBootSuggested() {
return getBoolean(R.string.start_at_boot_suggested_key, false);
}
public static void setStartAtBootSuggested() {
setBoolean(R.string.start_at_boot_suggested_key, true);
}
public static boolean contactIntegrationSuggested() {
return getBoolean(R.string.contact_integration_suggested_key, false);
}
public static void setContactIntegrationSuggested() {
setBoolean(R.string.contact_integration_suggested_key, true);
}
public static boolean isTranslationSuggested() {
return getBoolean(R.string.translation_suggested_key, false);
}
public static void setTranslationSuggested() {
setBoolean(R.string.translation_suggested_key, true);
}
public static boolean isDarkThemeSuggested() {
return getBoolean(R.string.dark_theme_suggested_key, false);
}
public static void setDarkThemeSuggested() {
setBoolean(R.string.dark_theme_suggested_key, true);
}
public static void setDarkTheme() {
setString(R.string.interface_theme_key, Application.getInstance().getString(
R.string.interface_theme_dark_value));
}
public static boolean isBatteryOptimizationDisableSuggested() {
return getBoolean(R.string.battery_optimization_disable_suggested_key, false);
}
public static void setBatteryOptimizationDisableSuggested() {
setBoolean(R.string.battery_optimization_disable_suggested_key, true);
}
/**
* @return Common status mode for all accounts or
* {@link StatusMode#available} if mode was not set.
*/
public static StatusMode statusMode() {
return StatusMode.valueOf(getString(R.string.status_mode_key,
StatusMode.available.name()));
}
public static void setStatusMode(StatusMode statusMode) {
setString(R.string.status_mode_key, statusMode.name());
}
/**
* @return Common status text for all accounts.
*/
public static String statusText() {
return getString(R.string.status_text_key, "");
}
public static void setStatusText(String statusText) {
setString(R.string.status_text_key, statusText);
}
@Override
public void onInitialized() {
incrementBootCount();
}
@Override
public void onMigrate(int toVersion) {
switch (toVersion) {
case 32:
setBoolean(R.string.chats_show_status_change_key, false);
break;
case 40:
String value;
try {
if (getBoolean(R.string.chats_show_status_change_key, false))
value = Application.getInstance().getString(
R.string.chats_show_status_change_always_value);
else
value = Application.getInstance().getString(
R.string.chats_show_status_change_muc_value);
} catch (ClassCastException e) {
value = Application.getInstance().getString(
R.string.chats_show_status_change_default);
}
setString(R.string.chats_show_status_change_key, value);
break;
case 45:
setBoolean(R.string.chats_show_avatars_key,
"message".equals(getString(R.string.chats_show_avatars_key,
"")));
break;
case 65:
SharedPreferences settings = Application.getInstance()
.getSharedPreferences("accounts", Context.MODE_PRIVATE);
int statusModeIndex = settings.getInt("status_mode",
StatusMode.available.ordinal());
StatusMode statusMode = StatusMode.values()[statusModeIndex];
setString(R.string.status_mode_key, statusMode.name());
String statusText = settings.getString("status_text", "");
setString(R.string.status_text_key, statusText);
break;
default:
break;
}
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
if (key.equals(Application.getInstance().getString(
R.string.chats_show_status_change_key))) {
MessageManager.getInstance().onSettingsChanged();
} else if (key.equals(Application.getInstance().getString(
R.string.events_persistent_key))) {
NotificationManager.getInstance().onMessageNotification();
XabberService.getInstance().changeForeground();
} else if (key.equals(Application.getInstance().getString(
R.string.connection_wake_lock_key))) {
WakeLockManager.onWakeLockSettingsChanged();
} else if (key.equals(Application.getInstance().getString(
R.string.connection_wifi_lock_key))) {
WakeLockManager.onWifiLockSettingsChanged();
} else if (key.equals(Application.getInstance().getString(
R.string.connection_use_carbons_key))) {
CarbonManager.getInstance().onUseCarbonsSettingsChanged();
} else if (key.equals(Application.getInstance().getString(
R.string.events_show_text_key))) {
NotificationManager.getInstance().onMessageNotification();
} else if (key.equals(Application.getInstance().getString(
R.string.chats_attention_key))) {
AttentionManager.getInstance().onSettingsChanged();
} else if (key.equals(Application.getInstance().getString(
R.string.security_otr_mode_key))) {
OTRManager.getInstance().onSettingsChanged();
} else if (key.equals(Application.getInstance().getString(
R.string.interface_theme_key))) {
ColorManager.getInstance().onSettingsChanged();
if (SettingsManager.interfaceTheme() == InterfaceTheme.dark) {
SettingsManager.setDarkThemeSuggested();
}
} else if(key.equals(Application.getInstance().getString(
R.string.debug_file_log_key))) {
LogManager.getInstance().onSettingsChanged();
}
}
public enum ChatsHistory {
/**
* Don't store chat messages.
*/
none,
/**
* Store only unread messages.
*/
unread,
/**
* Store all messages.
*/
all
}
public enum InterfaceTheme {
/**
* All windows will be dark.
*/
dark,
/**
* All windows will be light.
*/
light,
/**
* Chat will be light, other windows will be dark.
*/
normal
}
public enum DnsResolverType {
/**
* Use DNS resolver based on dnsjava
* http://dnsjava.org/
*/
dnsJavaResolver,
/**
* Use DNS resolver based on MiniDNS - experimental
* https://github.com/rtreffer/minidns
*/
miniDnsResolver
}
public enum EventsMessage {
/**
* Never notify.
*/
none,
/**
* Notify in chat only.
*/
chat,
/**
* Notify in chat and muc.
*/
chatAndMuc
}
public enum ChatsShowStatusChange {
/**
* Always show status change.
*/
always,
/**
* Show status change only in MUC.
*/
muc,
/**
* Never show status change.
*/
never
}
public enum ChatsHideKeyboard {
/**
* Always hide keyboard.
*/
always,
/**
* Hide keyboard only in landscape mode.
*/
landscape,
/**
* Never hide keyboard.
*/
never,
}
public enum SecurityOtrMode {
/**
* OTR is disabled.
*/
disabled,
/**
* Manually send request and confirm requests.
*/
manual,
/**
* Automatically try to use OTR.
*/
auto,
/**
* Require to use OTR.
*/
required
}
}