/**
* Wire
* Copyright (C) 2016 Wire Swiss GmbH
*
* This program 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.
*
* This program 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.waz.zclient.controllers.userpreferences;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import com.waz.zclient.R;
import com.waz.zclient.utils.StringUtils;
import org.json.JSONArray;
import org.json.JSONException;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
public class UserPreferencesController implements IUserPreferencesController {
public static final String USER_PREFS_TAG = "com.wire.preferences";
//TODO Move these preferences to the UserPreferences service in SE, since a lot of them are user-scoped anyway.
public static final String USER_PREFS_LAST_ACCENT_COLOR = "USER_PREFS_LAST_ACCENT_COLOR";
public static final String USER_PREFS_REFERRAL_TOKEN = "USER_PREFS_REFERRAL_TOKEN";
public static final String USER_PREFS_GENERIC_INVITATION_TOKEN = "USER_PREFS_GENERIC_INVITATION_TOKEN";
public static final String USER_PREFS_PERSONAL_INVITATION_TOKEN = "USER_PREFS_PERSONAL_INVITATION_TOKEN";
public static final String USER_PERFS_AB_TESTING_GROUP = "USER_PERFS_AB_TESTING_GROUP";
public static final String USER_PREF_PLAY_SERVICES_ERROR_SHOWN = "USER_PREF_PLAY_SERVICES_ERROR_SHOWN";
private static final String USER_PREFS_SHOW_SHARE_CONTACTS_DIALOG = "USER_PREFS_SHOW_SHARE_CONTACTS_DIALOG ";
private static final String USER_PREF_PHONE_VERIFICATION_CODE = "PREF_PHONE_VERIFICATION_CODE";
private static final String USER_PREF_APP_CRASH = "USER_PREF_APP_CRASH";
private static final String USER_PREF_APP_CRASH_DETAILS = "USER_PREF_APP_CRASH_DETAILS";
private static final String USER_PREF_LOGGED_IN = "USER_PREF_LOGGED_IN_%s";
private static final String USER_PREF_AB_TESTING_UUID = "USER_PREF_AB_TESTING_UUID";
private static final String USER_PREF_ACTION_PREFIX = "USER_PREF_ACTION_PREFIX";
private static final String USER_PREF_RECENT_EMOJIS = "USER_PREF_RECENT_EMOJIS";
private static final String USER_PREF_UNSUPPORTED_EMOJIS = "USER_PREF_UNSUPPORTED_EMOJIS";
private static final String USER_PREF_UNSUPPORTED_EMOJIS_CHECKED = "USER_PREF_UNSUPPORTED_EMOJIS_CHECKED";
private static final String USER_PREF_LAST_EPHEMERAL_VALUE = "USER_PREF_LAST_EPHEMERAL_VALUE";
private static final String PREFS_DEVICE_ID = "com.waz.device.id";
private static final int AB_TESTING_GROUP_COUNT = 6;
private final SharedPreferences userPreferences;
private Context context;
public UserPreferencesController(Context context) {
userPreferences = context.getSharedPreferences(USER_PREFS_TAG, Context.MODE_PRIVATE);
this.context = context;
}
@Override
public void tearDown() {
context = null;
}
@SuppressLint("CommitPrefEdits")
@Override
public void reset() {
// TODO: AN-2066 Should reset all preferences
}
public void setLastAccentColor(int accentColor) {
userPreferences.edit().putInt(USER_PREFS_LAST_ACCENT_COLOR, accentColor).apply();
}
public int getLastAccentColor() {
return userPreferences.getInt(USER_PREFS_LAST_ACCENT_COLOR, -1);
}
@Override
public boolean showContactsDialog() {
return userPreferences.getBoolean(USER_PREFS_SHOW_SHARE_CONTACTS_DIALOG, true);
}
@Override
public void setReferralToken(String token) {
userPreferences.edit().putString(USER_PREFS_REFERRAL_TOKEN, token).apply();
}
@Override
public String getReferralToken() {
return userPreferences.getString(USER_PREFS_REFERRAL_TOKEN, null);
}
@Override
public void setGenericInvitationToken(String token) {
userPreferences.edit().putString(USER_PREFS_GENERIC_INVITATION_TOKEN, token).apply();
}
@Override
public String getGenericInvitationToken() {
return userPreferences.getString(USER_PREFS_GENERIC_INVITATION_TOKEN, null);
}
@Override
public void setPersonalInvitationToken(String token) {
userPreferences.edit().putString(USER_PREFS_PERSONAL_INVITATION_TOKEN, token).apply();
}
@Override
public String getPersonalInvitationToken() {
return userPreferences.getString(USER_PREFS_PERSONAL_INVITATION_TOKEN, null);
}
@Override
public String getLastCallSessionId() {
return userPreferences.getString(context.getString(R.string.pref_dev_avs_last_call_session_id_key),
context.getString(R.string.pref_dev_avs_last_call_session_id_not_available));
}
@Override
public void setPostSessionIdToConversation(boolean postSessionIdToConversation) {
userPreferences.edit().putBoolean(context.getString(R.string.pref_dev_avs_post_session_id_key), postSessionIdToConversation).apply();
}
@Override
public boolean isPostSessionIdToConversation() {
return userPreferences.getBoolean(context.getString(R.string.pref_dev_avs_post_session_id_key), false);
}
@Override
public String getDeviceId() {
String id = userPreferences.getString(PREFS_DEVICE_ID, null);
if (id == null) {
id = getLegacyDeviceId();
if (id == null) {
id = UUID.randomUUID().toString();
}
userPreferences.edit()
.putString(PREFS_DEVICE_ID, id)
.apply();
}
return id;
}
private String getLegacyDeviceId() {
SharedPreferences prefs = context.getSharedPreferences("zprefs", Context.MODE_PRIVATE);
return prefs.getString(PREFS_DEVICE_ID, null);
}
@Override
public boolean isCursorSendButtonEnabled() {
return userPreferences.getBoolean(context.getString(R.string.pref_options_cursor_send_button_key), true);
}
@Override
public void setVerificationCode(String code) {
userPreferences.edit().putString(USER_PREF_PHONE_VERIFICATION_CODE, code).apply();
}
@Override
public void removeVerificationCode() {
userPreferences.edit().remove(USER_PREF_PHONE_VERIFICATION_CODE).apply();
}
@Override
public String getVerificationCode() {
return userPreferences.getString(USER_PREF_PHONE_VERIFICATION_CODE, null);
}
@Override
public boolean hasVerificationCode() {
return userPreferences.contains(USER_PREF_PHONE_VERIFICATION_CODE);
}
@Override
@SuppressWarnings("CommitPrefEdits")
public void setCrashException(String exception, String details) {
userPreferences.edit()
.putString(USER_PREF_APP_CRASH, exception)
.putString(USER_PREF_APP_CRASH_DETAILS, details)
.commit();
}
@Override
public String getCrashException() {
String exception = userPreferences.getString(USER_PREF_APP_CRASH, null);
if (exception != null) {
userPreferences.edit().putString(USER_PREF_APP_CRASH, null).apply();
}
return exception;
}
@Override
public String getCrashDetails() {
String details = userPreferences.getString(USER_PREF_APP_CRASH_DETAILS, null);
if (details != null) {
userPreferences.edit().putString(USER_PREF_APP_CRASH_DETAILS, null).apply();
}
return details;
}
@Override
public boolean hasUserLoggedIn(String userId) {
return userPreferences.getBoolean(String.format(USER_PREF_LOGGED_IN, userId), false);
}
@Override
public void userLoggedIn(String userId) {
userPreferences.edit().putBoolean(String.format(USER_PREF_LOGGED_IN, userId), true).apply();
}
@Override
public void setPerformedAction(@Action int action) {
userPreferences.edit().putBoolean(USER_PREF_ACTION_PREFIX + action, true).apply();
}
@Override
public boolean hasPerformedAction(@Action int action) {
return userPreferences.getBoolean(USER_PREF_ACTION_PREFIX + action, false);
}
@Override
public int getABTestingGroup() {
int group = userPreferences.getInt(USER_PERFS_AB_TESTING_GROUP, -1);
if (group == -1) {
UUID uuid = UUID.randomUUID();
userPreferences.edit().putString(USER_PREF_AB_TESTING_UUID, uuid.toString()).apply();
group = (int) Math.abs(uuid.getLeastSignificantBits() % AB_TESTING_GROUP_COUNT) + 1;
userPreferences.edit().putInt(USER_PERFS_AB_TESTING_GROUP, group).apply();
}
return group;
}
@Override
public void addRecentEmoji(String emoji) {
RecentEmojis recentEmojis = new RecentEmojis(userPreferences.getString(USER_PREF_RECENT_EMOJIS, null));
recentEmojis.addRecentEmoji(emoji);
userPreferences.edit().putString(USER_PREF_RECENT_EMOJIS, recentEmojis.getJson()).apply();
}
@Override
public List<String> getRecentEmojis() {
return new RecentEmojis(userPreferences.getString(USER_PREF_RECENT_EMOJIS, null)).getRecentEmojis();
}
@Override
public void setUnsupportedEmoji(Collection<String> emoji, int version) {
JSONArray array = new JSONArray();
for (String e : emoji) {
array.put(e);
}
userPreferences.edit()
.putString(USER_PREF_UNSUPPORTED_EMOJIS, array.toString())
.putInt(USER_PREF_UNSUPPORTED_EMOJIS_CHECKED, version)
.apply();
}
@Override
public Set<String> getUnsupportedEmojis() {
String json = userPreferences.getString(USER_PREF_UNSUPPORTED_EMOJIS, null);
Set<String> unsupportedEmojis = new HashSet<>();
if (!StringUtils.isBlank(json)) {
try {
JSONArray jsonArray = new JSONArray(json);
for (int i = 0; i < jsonArray.length(); i++) {
unsupportedEmojis.add(jsonArray.getString(i));
}
} catch (JSONException e) {
// ignore
}
}
return unsupportedEmojis;
}
@Override
public boolean hasCheckedForUnsupportedEmojis(int version) {
return userPreferences.getInt(USER_PREF_UNSUPPORTED_EMOJIS_CHECKED, 0) >= version;
}
@Override
public boolean hasShareContactsEnabled() {
return userPreferences.getBoolean(context.getString(R.string.pref_share_contacts_key), true);
}
@Override
public void setShareContactsEnabled(boolean enabled) {
userPreferences.edit().putBoolean(context.getString(R.string.pref_share_contacts_key), enabled).apply();
}
@Override
public long getLastEphemeralValue() {
return userPreferences.getLong(USER_PREF_LAST_EPHEMERAL_VALUE, 0);
}
@Override
public void setLastEphemeralValue(long value) {
userPreferences.edit().putLong(USER_PREF_LAST_EPHEMERAL_VALUE, value).apply();
}
@Override
public boolean hasPlayServicesErrorShown() {
return userPreferences.getBoolean(USER_PREF_PLAY_SERVICES_ERROR_SHOWN, false);
}
@Override
public void setPlayServicesErrorShown(boolean value) {
userPreferences.edit().putBoolean(USER_PREF_PLAY_SERVICES_ERROR_SHOWN, value).apply();
}
@Override
public boolean isVariableBitRateEnabled() {
return userPreferences.getBoolean(context.getString(R.string.pref_options_vbr_key), true);
}
@Override
public boolean swapForceVerboseLogging() {
String key = context.getString(R.string.pref_force_verbose_key);
boolean updated = !userPreferences.getBoolean(key, false);
userPreferences.edit().putBoolean(key, updated).apply();
return updated;
}
}