Java tutorial
/* * Copyright 2016 OpenMarket Ltd * Copyright 2017 Vector Creations Ltd * Copyright 2018 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package im.vector.fragments; import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Typeface; import android.media.RingtoneManager; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.preference.CheckBoxPreference; import android.preference.EditTextPreference; import android.preference.ListPreference; import android.preference.Preference; import android.preference.PreferenceCategory; import android.preference.PreferenceFragment; import android.preference.PreferenceManager; import android.preference.PreferenceScreen; import android.provider.Settings; import android.support.design.widget.TextInputEditText; import android.support.v4.content.ContextCompat; import android.text.Editable; import android.text.InputType; import android.text.TextUtils; import android.text.TextWatcher; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.widget.Button; import android.widget.CheckedTextView; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import com.bumptech.glide.Glide; import com.google.i18n.phonenumbers.NumberParseException; import com.google.i18n.phonenumbers.PhoneNumberUtil; import com.google.i18n.phonenumbers.Phonenumber; import org.matrix.androidsdk.MXSession; import org.matrix.androidsdk.crypto.data.MXDeviceInfo; import org.matrix.androidsdk.data.MyUser; import org.matrix.androidsdk.data.Pusher; import org.matrix.androidsdk.data.RoomMediaMessage; import org.matrix.androidsdk.db.MXMediasCache; import org.matrix.androidsdk.listeners.IMXNetworkEventListener; import org.matrix.androidsdk.listeners.MXEventListener; import org.matrix.androidsdk.listeners.MXMediaUploadListener; import org.matrix.androidsdk.rest.callback.ApiCallback; import org.matrix.androidsdk.rest.callback.SimpleApiCallback; import org.matrix.androidsdk.rest.model.MatrixError; import org.matrix.androidsdk.rest.model.bingrules.BingRule; import org.matrix.androidsdk.rest.model.bingrules.BingRuleSet; import org.matrix.androidsdk.rest.model.group.Group; import org.matrix.androidsdk.rest.model.pid.ThirdPartyIdentifier; import org.matrix.androidsdk.rest.model.pid.ThreePid; import org.matrix.androidsdk.rest.model.sync.DeviceInfo; import org.matrix.androidsdk.rest.model.sync.DevicesListResponse; import org.matrix.androidsdk.util.BingRulesManager; import org.matrix.androidsdk.util.Log; import org.matrix.androidsdk.util.ResourceUtils; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Set; import im.vector.Matrix; import im.vector.R; import im.vector.VectorApp; import im.vector.activity.CommonActivityUtils; import im.vector.activity.CountryPickerActivity; import im.vector.activity.DeactivateAccountActivity; import im.vector.activity.LanguagePickerActivity; import im.vector.activity.NotificationPrivacyActivity; import im.vector.activity.PhoneNumberAdditionActivity; import im.vector.activity.RiotAppCompatActivity; import im.vector.activity.VectorMediasPickerActivity; import im.vector.contacts.ContactsManager; import im.vector.gcm.GcmRegistrationManager; import im.vector.preference.BingRulePreference; import im.vector.preference.ProgressBarPreference; import im.vector.preference.UserAvatarPreference; import im.vector.preference.VectorCustomActionEditTextPreference; import im.vector.preference.VectorGroupPreference; import im.vector.preference.VectorSwitchPreference; import im.vector.util.PhoneNumberUtils; import im.vector.util.PreferencesManager; import im.vector.util.ThemeUtils; import im.vector.util.VectorUtils; public class VectorSettingsPreferencesFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String LOG_TAG = VectorSettingsPreferencesFragment.class.getSimpleName(); // arguments indexes private static final String ARG_MATRIX_ID = "VectorSettingsPreferencesFragment.ARG_MATRIX_ID"; private static final String EMAIL_PREFERENCE_KEY_BASE = "EMAIL_PREFERENCE_KEY_BASE"; private static final String PHONE_NUMBER_PREFERENCE_KEY_BASE = "PHONE_NUMBER_PREFERENCE_KEY_BASE"; private static final String PUSHER_PREFERENCE_KEY_BASE = "PUSHER_PREFERENCE_KEY_BASE"; private static final String DEVICES_PREFERENCE_KEY_BASE = "DEVICES_PREFERENCE_KEY_BASE"; private static final String IGNORED_USER_KEY_BASE = "IGNORED_USER_KEY_BASE"; private static final String ADD_EMAIL_PREFERENCE_KEY = "ADD_EMAIL_PREFERENCE_KEY"; private static final String ADD_PHONE_NUMBER_PREFERENCE_KEY = "ADD_PHONE_NUMBER_PREFERENCE_KEY"; private static final String APP_INFO_LINK_PREFERENCE_KEY = "application_info_link"; private static final String DUMMY_RULE = "DUMMY_RULE"; private static final String LABEL_UNAVAILABLE_DATA = "none"; private static final int REQUEST_E2E_FILE_REQUEST_CODE = 123; private static final int REQUEST_NEW_PHONE_NUMBER = 456; private static final int REQUEST_PHONEBOOK_COUNTRY = 789; private static final int REQUEST_LOCALE = 777; private static final int REQUEST_NOTIFICATION_RINGTONE = 888; // rule Id <-> preference name private static HashMap<String, String> mPushesRuleByResourceId = null; // members private MXSession mSession; // disable some updates if there is private final IMXNetworkEventListener mNetworkListener = new IMXNetworkEventListener() { @Override public void onNetworkConnectionUpdate(boolean isConnected) { refreshDisplay(); } }; // events listener private final MXEventListener mEventsListener = new MXEventListener() { @Override public void onBingRulesUpdate() { refreshPreferences(); refreshDisplay(); } @Override public void onAccountInfoUpdate(MyUser myUser) { // refresh the settings value SharedPreferences preferences = PreferenceManager .getDefaultSharedPreferences(VectorApp.getInstance().getApplicationContext()); SharedPreferences.Editor editor = preferences.edit(); editor.putString(PreferencesManager.SETTINGS_DISPLAY_NAME_PREFERENCE_KEY, myUser.displayname); editor.commit(); refreshDisplay(); } }; private View mLoadingView; // cryptography private DeviceInfo mMyDeviceInfo; private PreferenceCategory mCryptographyCategory; private PreferenceCategory mCryptographyCategoryDivider; // displayed emails private PreferenceCategory mUserSettingsCategory; private List<String> mDisplayedEmails = new ArrayList<>(); private List<String> mDisplayedPhoneNumber = new ArrayList<>(); // Local contacts private PreferenceCategory mContactSettingsCategory; private VectorCustomActionEditTextPreference mContactPhonebookCountryPreference; // displayed pushers private PreferenceCategory mPushersSettingsDivider; private PreferenceCategory mPushersSettingsCategory; private List<Pusher> mDisplayedPushers = new ArrayList<>(); // devices: device IDs and device names private PreferenceCategory mDevicesListSettingsCategory; private PreferenceCategory mDevicesListSettingsCategoryDivider; private List<DeviceInfo> mDevicesNameList = new ArrayList<>(); // used to avoid requesting to enter the password for each deletion private String mAccountPassword; // displayed the ignored users list private PreferenceCategory mIgnoredUserSettingsCategoryDivider; private PreferenceCategory mIgnoredUserSettingsCategory; // background sync category private EditTextPreference mSyncRequestTimeoutPreference; private EditTextPreference mSyncRequestDelayPreference; private PreferenceCategory mLabsCategory; private PreferenceCategory mGroupsFlairCategory; // static constructor public static VectorSettingsPreferencesFragment newInstance(String matrixId) { VectorSettingsPreferencesFragment f = new VectorSettingsPreferencesFragment(); Bundle args = new Bundle(); args.putString(ARG_MATRIX_ID, matrixId); f.setArguments(args); return f; } @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); final Context appContext = getActivity().getApplicationContext(); // retrieve the arguments Bundle args = getArguments(); String matrixId = args.getString(ARG_MATRIX_ID); mSession = Matrix.getInstance(appContext).getSession(matrixId); // sanity checks if ((null == mSession) || !mSession.isAlive()) { getActivity().finish(); return; } // define the layout addPreferencesFromResource(R.xml.vector_settings_preferences); if (null == mPushesRuleByResourceId) { mPushesRuleByResourceId = new HashMap<>(); mPushesRuleByResourceId.put(PreferencesManager.SETTINGS_ENABLE_ALL_NOTIF_PREFERENCE_KEY, BingRule.RULE_ID_DISABLE_ALL); mPushesRuleByResourceId.put(PreferencesManager.SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY, DUMMY_RULE); mPushesRuleByResourceId.put(PreferencesManager.SETTINGS_TURN_SCREEN_ON_PREFERENCE_KEY, DUMMY_RULE); mPushesRuleByResourceId.put(PreferencesManager.SETTINGS_CONTAINING_MY_DISPLAY_NAME_PREFERENCE_KEY, BingRule.RULE_ID_CONTAIN_DISPLAY_NAME); mPushesRuleByResourceId.put(PreferencesManager.SETTINGS_CONTAINING_MY_USER_NAME_PREFERENCE_KEY, BingRule.RULE_ID_CONTAIN_USER_NAME); mPushesRuleByResourceId.put(PreferencesManager.SETTINGS_MESSAGES_IN_ONE_TO_ONE_PREFERENCE_KEY, BingRule.RULE_ID_ONE_TO_ONE_ROOM); mPushesRuleByResourceId.put(PreferencesManager.SETTINGS_MESSAGES_IN_GROUP_CHAT_PREFERENCE_KEY, BingRule.RULE_ID_ALL_OTHER_MESSAGES_ROOMS); mPushesRuleByResourceId.put(PreferencesManager.SETTINGS_INVITED_TO_ROOM_PREFERENCE_KEY, BingRule.RULE_ID_INVITE_ME); mPushesRuleByResourceId.put(PreferencesManager.SETTINGS_CALL_INVITATIONS_PREFERENCE_KEY, BingRule.RULE_ID_CALL); mPushesRuleByResourceId.put(PreferencesManager.SETTINGS_MESSAGES_SENT_BY_BOT_PREFERENCE_KEY, BingRule.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS); } UserAvatarPreference avatarPreference = (UserAvatarPreference) findPreference( PreferencesManager.SETTINGS_PROFILE_PICTURE_PREFERENCE_KEY); avatarPreference.setSession(mSession); avatarPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { onUpdateAvatarClick(); return false; } }); EditTextPreference passwordPreference = (EditTextPreference) findPreference( PreferencesManager.SETTINGS_CHANGE_PASSWORD_PREFERENCE_KEY); passwordPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { onPasswordUpdateClick(); return false; } }); EditTextPreference notificationRingTonePreference = (EditTextPreference) findPreference( PreferencesManager.SETTINGS_NOTIFICATION_RINGTONE_SELECTION_PREFERENCE_KEY); notificationRingTonePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER); intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION); if (null != PreferencesManager.getNotificationRingTone(getActivity())) { intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, PreferencesManager.getNotificationRingTone(getActivity())); } getActivity().startActivityForResult(intent, REQUEST_NOTIFICATION_RINGTONE); return false; } }); refreshNotificationRingTone(); EditTextPreference notificationPrivacyPreference = (EditTextPreference) findPreference( PreferencesManager.SETTINGS_NOTIFICATION_PRIVACY_PREFERENCE_KEY); if (notificationPrivacyPreference != null) { notificationPrivacyPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { startActivity(NotificationPrivacyActivity.getIntent(getActivity())); return true; } }); refreshNotificationPrivacy(); } // application version VectorCustomActionEditTextPreference versionTextPreference = (VectorCustomActionEditTextPreference) findPreference( PreferencesManager.SETTINGS_VERSION_PREFERENCE_KEY); if (null != versionTextPreference) { versionTextPreference.setSummary(VectorUtils.getApplicationVersion(appContext)); versionTextPreference.setOnPreferenceLongClickListener( new VectorCustomActionEditTextPreference.OnPreferenceLongClickListener() { @Override public boolean onPreferenceLongClick(Preference preference) { VectorUtils.copyToClipboard(appContext, VectorUtils.getApplicationVersion(appContext)); return true; } }); } // olm version EditTextPreference olmTextPreference = (EditTextPreference) findPreference( PreferencesManager.SETTINGS_OLM_VERSION_PREFERENCE_KEY); if (null != olmTextPreference) { olmTextPreference.setSummary( Matrix.getInstance(appContext).getDefaultSession().getCryptoVersion(appContext, false)); } // user account EditTextPreference accountIdTextPreference = (EditTextPreference) findPreference( PreferencesManager.SETTINGS_LOGGED_IN_PREFERENCE_KEY); if (null != accountIdTextPreference) { accountIdTextPreference.setSummary(mSession.getMyUserId()); } // home server EditTextPreference homeServerTextPreference = (EditTextPreference) findPreference( PreferencesManager.SETTINGS_HOME_SERVER_PREFERENCE_KEY); if (null != homeServerTextPreference) { homeServerTextPreference.setSummary(mSession.getHomeServerConfig().getHomeserverUri().toString()); } // identity server EditTextPreference identityServerTextPreference = (EditTextPreference) findPreference( PreferencesManager.SETTINGS_IDENTITY_SERVER_PREFERENCE_KEY); if (null != identityServerTextPreference) { identityServerTextPreference .setSummary(mSession.getHomeServerConfig().getIdentityServerUri().toString()); } // terms & conditions EditTextPreference termConditionsPreference = (EditTextPreference) findPreference( PreferencesManager.SETTINGS_APP_TERM_CONDITIONS_PREFERENCE_KEY); if (null != termConditionsPreference) { termConditionsPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { VectorUtils.displayAppTac(); return false; } }); } // Themes ListPreference themePreference = (ListPreference) findPreference(ThemeUtils.APPLICATION_THEME_KEY); if (null != themePreference) { themePreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { if (newValue instanceof String) { VectorApp.updateApplicationTheme((String) newValue); getActivity().startActivity(getActivity().getIntent()); getActivity().finish(); return true; } else { return false; } } }); } // privacy policy EditTextPreference privacyPreference = (EditTextPreference) findPreference( PreferencesManager.SETTINGS_PRIVACY_POLICY_PREFERENCE_KEY); if (null != privacyPreference) { privacyPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { VectorUtils.displayAppPrivacyPolicy(); return false; } }); } // third party notice EditTextPreference thirdPartyNotices = (EditTextPreference) findPreference( PreferencesManager.SETTINGS_THIRD_PARTY_NOTICES_PREFERENCE_KEY); if (null != thirdPartyNotices) { thirdPartyNotices.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { VectorUtils.displayThirdPartyLicenses(); return false; } }); } // copyright EditTextPreference copyrightNotices = (EditTextPreference) findPreference( PreferencesManager.SETTINGS_COPYRIGHT_PREFERENCE_KEY); if (null != copyrightNotices) { copyrightNotices.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { VectorUtils.displayAppCopyright(); return false; } }); } // update keep medias period final EditTextPreference keepMediaPeriodPreference = (EditTextPreference) findPreference( PreferencesManager.SETTINGS_MEDIA_SAVING_PERIOD_KEY); if (null != keepMediaPeriodPreference) { keepMediaPeriodPreference .setSummary(PreferencesManager.getSelectedMediasSavingPeriodString(getActivity())); keepMediaPeriodPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { new AlertDialog.Builder(getActivity()) .setSingleChoiceItems(PreferencesManager.getMediasSavingItemsChoicesList(getActivity()), PreferencesManager.getSelectedMediasSavingPeriod(getActivity()), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface d, int n) { PreferencesManager.setSelectedMediasSavingPeriod(getActivity(), n); d.cancel(); keepMediaPeriodPreference.setSummary(PreferencesManager .getSelectedMediasSavingPeriodString(getActivity())); } }) .show(); return false; } }); } // clear medias cache final EditTextPreference clearMediaCachePreference = (EditTextPreference) findPreference( PreferencesManager.SETTINGS_CLEAR_MEDIA_CACHE_PREFERENCE_KEY); if (null != clearMediaCachePreference) { MXMediasCache.getCachesSize(getActivity(), new SimpleApiCallback<Long>() { @Override public void onSuccess(Long size) { if (null != getActivity()) { clearMediaCachePreference .setSummary(android.text.format.Formatter.formatFileSize(getActivity(), size)); } } }); clearMediaCachePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { displayLoadingView(); AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { mSession.getMediasCache().clear(); Glide.get(getActivity()).clearDiskCache(); return null; } @Override protected void onPostExecute(Void result) { hideLoadingView(); MXMediasCache.getCachesSize(getActivity(), new SimpleApiCallback<Long>() { @Override public void onSuccess(Long size) { clearMediaCachePreference.setSummary( android.text.format.Formatter.formatFileSize(getActivity(), size)); } }); } }; try { task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } catch (Exception e) { Log.e(LOG_TAG, "## mSession.getMediasCache().clear() failed " + e.getMessage()); task.cancel(true); hideLoadingView(); } return false; } }); } // clear cache final EditTextPreference clearCachePreference = (EditTextPreference) findPreference( PreferencesManager.SETTINGS_CLEAR_CACHE_PREFERENCE_KEY); if (null != clearCachePreference) { MXSession.getApplicationSizeCaches(getActivity(), new SimpleApiCallback<Long>() { @Override public void onSuccess(Long size) { if (null != getActivity()) { clearCachePreference .setSummary(android.text.format.Formatter.formatFileSize(getActivity(), size)); } } }); clearCachePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { displayLoadingView(); Matrix.getInstance(appContext).reloadSessions(appContext); return false; } }); } final EditTextPreference displaynamePref = (EditTextPreference) findPreference( PreferencesManager.SETTINGS_DISPLAY_NAME_PREFERENCE_KEY); displaynamePref.setSummary(mSession.getMyUser().displayname); displaynamePref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { onDisplayNameClick((null == newValue) ? null : ((String) newValue).trim()); return false; } }); final VectorSwitchPreference urlPreviewPreference = (VectorSwitchPreference) findPreference( PreferencesManager.SETTINGS_SHOW_URL_PREVIEW_KEY); urlPreviewPreference.setChecked(mSession.isURLPreviewEnabled()); urlPreviewPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { if ((null != newValue) && ((boolean) newValue != mSession.isURLPreviewEnabled())) { displayLoadingView(); mSession.setURLPreviewStatus((boolean) newValue, new ApiCallback<Void>() { @Override public void onSuccess(Void info) { urlPreviewPreference.setChecked(mSession.isURLPreviewEnabled()); hideLoadingView(); } private void onError(String errorMessage) { if (null != getActivity()) { Toast.makeText(getActivity(), errorMessage, Toast.LENGTH_SHORT).show(); } onSuccess(null); } @Override public void onNetworkError(Exception e) { onError(e.getLocalizedMessage()); } @Override public void onMatrixError(MatrixError e) { onError(e.getLocalizedMessage()); } @Override public void onUnexpectedError(Exception e) { onError(e.getLocalizedMessage()); } }); } return false; } }); // push rules for (String resourceText : mPushesRuleByResourceId.keySet()) { final Preference preference = findPreference(resourceText); if (null != preference) { if (preference instanceof CheckBoxPreference) { preference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValueAsVoid) { // on some old android APIs, // the callback is called even if there is no user interaction // so the value will be checked to ensure there is really no update. onPushRuleClick(preference.getKey(), (boolean) newValueAsVoid); return true; } }); } else if (preference instanceof BingRulePreference) { final BingRulePreference bingRulePreference = (BingRulePreference) preference; bingRulePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { new AlertDialog.Builder(getActivity()).setSingleChoiceItems( bingRulePreference.getBingRuleStatuses(), bingRulePreference.getRuleStatusIndex(), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface d, int index) { BingRule rule = bingRulePreference.createRule(index); d.cancel(); if (null != rule) { displayLoadingView(); mSession.getDataHandler().getBingRulesManager().updateRule( bingRulePreference.getRule(), rule, new BingRulesManager.onBingRuleUpdateListener() { private void onDone() { refreshDisplay(); hideLoadingView(); } @Override public void onBingRuleUpdateSuccess() { onDone(); } @Override public void onBingRuleUpdateFailure( String errorMessage) { if (null != getActivity()) { Toast.makeText(getActivity(), errorMessage, Toast.LENGTH_SHORT).show(); } onDone(); } }); } } }).show(); return true; } }); } } } // background sync tuning settings // these settings are useless and hidden if the app is registered to the GCM push service final GcmRegistrationManager gcmMgr = Matrix.getInstance(appContext).getSharedGCMRegistrationManager(); if (gcmMgr.useGCM() && gcmMgr.hasRegistrationToken()) { // Hide the section PreferenceScreen preferenceScreen = getPreferenceScreen(); PreferenceCategory backgroundSyncCategory = (PreferenceCategory) findPreference( PreferencesManager.SETTINGS_BACKGROUND_SYNC_PREFERENCE_KEY); PreferenceCategory backgroundSyncDivider = (PreferenceCategory) findPreference( PreferencesManager.SETTINGS_BACKGROUND_SYNC_DIVIDER_PREFERENCE_KEY); preferenceScreen.removePreference(backgroundSyncDivider); preferenceScreen.removePreference(backgroundSyncCategory); } else { mSyncRequestTimeoutPreference = (EditTextPreference) findPreference( PreferencesManager.SETTINGS_SET_SYNC_TIMEOUT_PREFERENCE_KEY); mSyncRequestDelayPreference = (EditTextPreference) findPreference( PreferencesManager.SETTINGS_SET_SYNC_DELAY_PREFERENCE_KEY); final CheckBoxPreference useBackgroundSyncPref = (CheckBoxPreference) findPreference( PreferencesManager.SETTINGS_ENABLE_BACKGROUND_SYNC_PREFERENCE_KEY); if (null != useBackgroundSyncPref) { final GcmRegistrationManager.ThirdPartyRegistrationListener listener = new GcmRegistrationManager.ThirdPartyRegistrationListener() { @Override public void onThirdPartyRegistered() { hideLoadingView(); } @Override public void onThirdPartyRegistrationFailed() { hideLoadingView(); } @Override public void onThirdPartyUnregistered() { hideLoadingView(); } @Override public void onThirdPartyUnregistrationFailed() { hideLoadingView(); } }; if (null != useBackgroundSyncPref) { useBackgroundSyncPref.setChecked(gcmMgr.isBackgroundSyncAllowed()); useBackgroundSyncPref .setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object aNewValue) { final boolean newValue = (boolean) aNewValue; if (newValue != gcmMgr.isBackgroundSyncAllowed()) { gcmMgr.setBackgroundSyncAllowed(newValue); } displayLoadingView(); Matrix.getInstance(VectorSettingsPreferencesFragment.this.getActivity()) .getSharedGCMRegistrationManager().forceSessionsRegistration(listener); return true; } }); } } } mUserSettingsCategory = (PreferenceCategory) findPreference( PreferencesManager.SETTINGS_USER_SETTINGS_PREFERENCE_KEY); mContactSettingsCategory = (PreferenceCategory) findPreference( PreferencesManager.SETTINGS_CONTACT_PREFERENCE_KEYS); mPushersSettingsCategory = (PreferenceCategory) findPreference( PreferencesManager.SETTINGS_NOTIFICATIONS_TARGETS_PREFERENCE_KEY); mPushersSettingsDivider = (PreferenceCategory) findPreference( PreferencesManager.SETTINGS_NOTIFICATIONS_TARGET_DIVIDER_PREFERENCE_KEY); mIgnoredUserSettingsCategory = (PreferenceCategory) findPreference( PreferencesManager.SETTINGS_IGNORED_USERS_PREFERENCE_KEY); mIgnoredUserSettingsCategoryDivider = (PreferenceCategory) findPreference( PreferencesManager.SETTINGS_IGNORE_USERS_DIVIDER_PREFERENCE_KEY); mDevicesListSettingsCategory = (PreferenceCategory) findPreference( PreferencesManager.SETTINGS_DEVICES_LIST_PREFERENCE_KEY); mDevicesListSettingsCategoryDivider = (PreferenceCategory) findPreference( PreferencesManager.SETTINGS_DEVICES_DIVIDER_PREFERENCE_KEY); mCryptographyCategory = (PreferenceCategory) findPreference( PreferencesManager.SETTINGS_CRYPTOGRAPHY_PREFERENCE_KEY); mCryptographyCategoryDivider = (PreferenceCategory) findPreference( PreferencesManager.SETTINGS_CRYPTOGRAPHY_DIVIDER_PREFERENCE_KEY); mLabsCategory = (PreferenceCategory) findPreference(PreferencesManager.SETTINGS_LABS_PREFERENCE_KEY); mGroupsFlairCategory = (PreferenceCategory) findPreference(PreferencesManager.SETTINGS_GROUPS_FLAIR_KEY); // preference to start the App info screen, to facilitate App permissions access Preference applicationInfoLInkPref = findPreference(APP_INFO_LINK_PREFERENCE_KEY); applicationInfoLInkPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { if (null != getActivity()) { Intent intent = new Intent(); intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); Uri uri = Uri.fromParts("package", appContext.getPackageName(), null); intent.setData(uri); getActivity().getApplicationContext().startActivity(intent); } return true; } }); // Contacts setContactsPreferences(); // user interface preferences setUserInterfacePreferences(); final CheckBoxPreference useCryptoPref = (CheckBoxPreference) findPreference( PreferencesManager.SETTINGS_ROOM_SETTINGS_LABS_END_TO_END_PREFERENCE_KEY); final Preference cryptoIsEnabledPref = findPreference( PreferencesManager.SETTINGS_ROOM_SETTINGS_LABS_END_TO_END_IS_ACTIVE_PREFERENCE_KEY); cryptoIsEnabledPref.setEnabled(false); if (!mSession.isCryptoEnabled()) { useCryptoPref.setChecked(false); mLabsCategory.removePreference(cryptoIsEnabledPref); } else { mLabsCategory.removePreference(useCryptoPref); } useCryptoPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValueAsVoid) { if (TextUtils.isEmpty(mSession.getCredentials().deviceId)) { new AlertDialog.Builder(getActivity()) .setMessage(R.string.room_settings_labs_end_to_end_warnings) .setPositiveButton(R.string.logout, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); CommonActivityUtils.logout(getActivity()); } }).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); useCryptoPref.setChecked(false); } }).setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { dialog.dismiss(); useCryptoPref.setChecked(false); } }).create().show(); } else { boolean newValue = (boolean) newValueAsVoid; if (mSession.isCryptoEnabled() != newValue) { displayLoadingView(); mSession.enableCrypto(newValue, new ApiCallback<Void>() { private void refresh() { if (null != getActivity()) { getActivity().runOnUiThread(new Runnable() { @Override public void run() { hideLoadingView(); useCryptoPref.setChecked(mSession.isCryptoEnabled()); if (mSession.isCryptoEnabled()) { mLabsCategory.removePreference(useCryptoPref); mLabsCategory.addPreference(cryptoIsEnabledPref); } } }); } } @Override public void onSuccess(Void info) { useCryptoPref.setEnabled(false); refresh(); } @Override public void onNetworkError(Exception e) { useCryptoPref.setChecked(false); } @Override public void onMatrixError(MatrixError e) { useCryptoPref.setChecked(false); } @Override public void onUnexpectedError(Exception e) { useCryptoPref.setChecked(false); } }); } } return true; } }); // SaveMode Managment final CheckBoxPreference dataSaveModePref = (CheckBoxPreference) findPreference( PreferencesManager.SETTINGS_DATA_SAVE_MODE_PREFERENCE_KEY); dataSaveModePref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { List<MXSession> sessions = Matrix.getMXSessions(getActivity()); for (MXSession session : sessions) { session.setUseDataSaveMode((boolean) newValue); } return true; } }); // Analytics tracking managment final CheckBoxPreference useAnalyticsModePref = (CheckBoxPreference) findPreference( PreferencesManager.SETTINGS_USE_ANALYTICS_KEY); // On if the analytics tracking is activated useAnalyticsModePref.setChecked(PreferencesManager.useAnalytics(appContext)); useAnalyticsModePref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { PreferencesManager.setUseAnalytics(appContext, (boolean) newValue); return true; } }); // Rageshake Managment final CheckBoxPreference useRageShakeModePref = (CheckBoxPreference) findPreference( PreferencesManager.SETTINGS_USE_RAGE_SHAKE_KEY); final boolean mIsUsedRageShake = PreferencesManager.useRageshake(appContext); useRageShakeModePref.setChecked(mIsUsedRageShake); useRageShakeModePref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { PreferencesManager.setUseRageshake(appContext, (boolean) newValue); return true; } }); // deactivate account EditTextPreference deactivateAccountPref = (EditTextPreference) findPreference( PreferencesManager.SETTINGS_DEACTIVATE_ACCOUNT_KEY); if (null != deactivateAccountPref) { deactivateAccountPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { startActivity(DeactivateAccountActivity.Companion.getIntent(getActivity())); return false; } }); } addButtons(); refreshPushersList(); refreshEmailsList(); refreshPhoneNumbersList(); refreshIgnoredUsersList(); refreshDevicesList(); refreshGroupFlairsList(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = super.onCreateView(inflater, container, savedInstanceState); if (null != view) { View listView = view.findViewById(android.R.id.list); if (null != listView) { listView.setPadding(0, 0, 0, 0); } } return view; } @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { // if the user toggles the contacts book permission if (TextUtils.equals(key, ContactsManager.CONTACTS_BOOK_ACCESS_KEY)) { // reset the current snapshot ContactsManager.getInstance().clearSnapshot(); } } @Override public void onPause() { super.onPause(); final Context context = getActivity().getApplicationContext(); if (mSession.isAlive()) { mSession.getDataHandler().removeListener(mEventsListener); Matrix.getInstance(context).removeNetworkEventListener(mNetworkListener); } PreferenceManager.getDefaultSharedPreferences(context).unregisterOnSharedPreferenceChangeListener(this); } @Override public void onResume() { super.onResume(); if (mSession.isAlive()) { final Context context = getActivity().getApplicationContext(); mSession.getDataHandler().addListener(mEventsListener); Matrix.getInstance(context).addNetworkEventListener(mNetworkListener); mSession.getMyUser().refreshThirdPartyIdentifiers(new SimpleApiCallback<Void>() { @Override public void onSuccess(Void info) { // ensure that the activity still exists if (null != getActivity()) { // and the result is called in the right thread getActivity().runOnUiThread(new Runnable() { @Override public void run() { refreshEmailsList(); refreshPhoneNumbersList(); } }); } } }); Matrix.getInstance(context).getSharedGCMRegistrationManager() .refreshPushersList(Matrix.getInstance(context).getSessions(), new SimpleApiCallback<Void>() { @Override public void onSuccess(Void info) { refreshPushersList(); } }); PreferenceManager.getDefaultSharedPreferences(context).registerOnSharedPreferenceChangeListener(this); // refresh anything else refreshPreferences(); refreshNotificationPrivacy(); refreshDisplay(); refreshBackgroundSyncPrefs(); } } //============================================================================================================== // Display methods //============================================================================================================== /** * Display the loading view. */ private void displayLoadingView() { // search the loading view from the upper view if (null == mLoadingView) { View parent = getView(); while ((parent != null) && (mLoadingView == null)) { mLoadingView = parent.findViewById(R.id.vector_settings_spinner_views); parent = (View) parent.getParent(); } } if (null != mLoadingView) { mLoadingView.setVisibility(View.VISIBLE); } } /** * Hide the loading view. */ private void hideLoadingView() { if (null != mLoadingView) { mLoadingView.setVisibility(View.GONE); } } /** * Hide the loading view and refresh the preferences. * * @param refresh true to refresh the display */ private void hideLoadingView(boolean refresh) { mLoadingView.setVisibility(View.GONE); if (refresh) { refreshDisplay(); } } /** * Refresh the preferences. */ private void refreshDisplay() { boolean isConnected = Matrix.getInstance(getActivity()).isConnected(); Context appContext = getActivity().getApplicationContext(); PreferenceManager preferenceManager = getPreferenceManager(); // refresh the avatar UserAvatarPreference avatarPreference = (UserAvatarPreference) preferenceManager .findPreference(PreferencesManager.SETTINGS_PROFILE_PICTURE_PREFERENCE_KEY); avatarPreference.refreshAvatar(); avatarPreference.setEnabled(isConnected); // refresh the display name final EditTextPreference displaynamePref = (EditTextPreference) preferenceManager .findPreference(PreferencesManager.SETTINGS_DISPLAY_NAME_PREFERENCE_KEY); displaynamePref.setSummary(mSession.getMyUser().displayname); displaynamePref.setText(mSession.getMyUser().displayname); displaynamePref.setEnabled(isConnected); // change password final EditTextPreference changePasswordPref = (EditTextPreference) preferenceManager .findPreference(PreferencesManager.SETTINGS_CHANGE_PASSWORD_PREFERENCE_KEY); changePasswordPref.setEnabled(isConnected); // update the push rules SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(appContext); BingRuleSet rules = mSession.getDataHandler().pushRules(); GcmRegistrationManager gcmMgr = Matrix.getInstance(appContext).getSharedGCMRegistrationManager(); for (String resourceText : mPushesRuleByResourceId.keySet()) { Preference preference = preferenceManager.findPreference(resourceText); if (null != preference) { if (preference instanceof BingRulePreference) { BingRulePreference bingRulePreference = (BingRulePreference) preference; bingRulePreference .setEnabled((null != rules) && isConnected && gcmMgr.areDeviceNotificationsAllowed()); bingRulePreference.setBingRule(mSession.getDataHandler().pushRules() .findDefaultRule(mPushesRuleByResourceId.get(resourceText))); } else if (preference instanceof CheckBoxPreference) { CheckBoxPreference switchPreference = (CheckBoxPreference) preference; if (resourceText.equals(PreferencesManager.SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY)) { switchPreference.setChecked(gcmMgr.areDeviceNotificationsAllowed()); } else if (resourceText.equals(PreferencesManager.SETTINGS_TURN_SCREEN_ON_PREFERENCE_KEY)) { switchPreference.setChecked(gcmMgr.isScreenTurnedOn()); switchPreference.setEnabled(gcmMgr.areDeviceNotificationsAllowed()); } else { switchPreference.setEnabled((null != rules) && isConnected); switchPreference.setChecked(preferences.getBoolean(resourceText, false)); } } } } // If notifications are disabled for the current user account or for the current user device // The others notifications settings have to be disable too boolean areNotifAllowed = rules != null && rules.findDefaultRule(BingRule.RULE_ID_DISABLE_ALL) != null && rules.findDefaultRule(BingRule.RULE_ID_DISABLE_ALL).isEnabled; Preference notificationSoundPreference = preferenceManager .findPreference(PreferencesManager.SETTINGS_NOTIFICATION_RINGTONE_SELECTION_PREFERENCE_KEY); notificationSoundPreference.setEnabled(!areNotifAllowed && gcmMgr.areDeviceNotificationsAllowed()); Preference notificationPrivacyPreference = preferenceManager .findPreference(PreferencesManager.SETTINGS_NOTIFICATION_PRIVACY_PREFERENCE_KEY); if (notificationPrivacyPreference != null) { notificationPrivacyPreference .setEnabled(!areNotifAllowed && gcmMgr.areDeviceNotificationsAllowed() && gcmMgr.useGCM()); } } private void addButtons() { // display the "add email" entry EditTextPreference addEmailPreference = new EditTextPreference(getActivity()); addEmailPreference.setTitle(R.string.settings_add_email_address); addEmailPreference.setDialogTitle(R.string.settings_add_email_address); addEmailPreference.setKey(ADD_EMAIL_PREFERENCE_KEY); addEmailPreference.setIcon(CommonActivityUtils.tintDrawable(getActivity(), ContextCompat.getDrawable(getActivity(), R.drawable.ic_add_black), R.attr.settings_icon_tint_color)); addEmailPreference.setOrder(100); addEmailPreference.getEditText() .setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS); addEmailPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { final String email = (null == newValue) ? null : ((String) newValue).trim(); getActivity().runOnUiThread(new Runnable() { @Override public void run() { addEmail(email); } }); return false; } }); mUserSettingsCategory.addPreference(addEmailPreference); // display the "add phone number" entry Preference addPhoneNumberPreference = new Preference(getActivity()); addPhoneNumberPreference.setKey(ADD_PHONE_NUMBER_PREFERENCE_KEY); addPhoneNumberPreference.setIcon(CommonActivityUtils.tintDrawable(getActivity(), ContextCompat.getDrawable(getActivity(), R.drawable.ic_add_black), R.attr.settings_icon_tint_color)); addPhoneNumberPreference.setTitle(R.string.settings_add_phone_number); addPhoneNumberPreference.setOrder(200); addPhoneNumberPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { Intent intent = PhoneNumberAdditionActivity.getIntent(getActivity(), mSession.getCredentials().userId); startActivityForResult(intent, REQUEST_NEW_PHONE_NUMBER); return true; } }); mUserSettingsCategory.addPreference(addPhoneNumberPreference); } //============================================================================================================== // Update items methods //============================================================================================================== /** * Update the password. */ private void onPasswordUpdateClick() { getActivity().runOnUiThread(new Runnable() { @Override public void run() { AlertDialog.Builder alertDialog = new AlertDialog.Builder(getActivity()); final View view = getActivity().getLayoutInflater() .inflate(R.layout.fragment_dialog_change_password, null); alertDialog.setView(view); alertDialog.setTitle(getString(R.string.settings_change_password)); final EditText oldPasswordText = view.findViewById(R.id.change_password_old_pwd_text); final EditText newPasswordText = view.findViewById(R.id.change_password_new_pwd_text); final EditText confirmNewPasswordText = view .findViewById(R.id.change_password_confirm_new_pwd_text); // Setting Positive "Yes" Button alertDialog.setPositiveButton(R.string.save, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { if (null != getActivity()) { InputMethodManager imm = (InputMethodManager) getActivity() .getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(view.getApplicationWindowToken(), 0); } String oldPwd = oldPasswordText.getText().toString().trim(); String newPwd = newPasswordText.getText().toString().trim(); displayLoadingView(); mSession.updatePassword(oldPwd, newPwd, new ApiCallback<Void>() { private void onDone(final int textId) { // check the activity still exists if (null != getActivity()) { // and the code is called in the right thread getActivity().runOnUiThread(new Runnable() { @Override public void run() { hideLoadingView(); Toast.makeText(getActivity(), getString(textId), Toast.LENGTH_LONG) .show(); } }); } } @Override public void onSuccess(Void info) { onDone(R.string.settings_password_updated); } @Override public void onNetworkError(Exception e) { onDone(R.string.settings_fail_to_update_password); } @Override public void onMatrixError(MatrixError e) { onDone(R.string.settings_fail_to_update_password); } @Override public void onUnexpectedError(Exception e) { onDone(R.string.settings_fail_to_update_password); } }); } }); // Setting Negative "NO" Button alertDialog.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { if (null != getActivity()) { InputMethodManager imm = (InputMethodManager) getActivity() .getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(view.getApplicationWindowToken(), 0); } } }); AlertDialog dialog = alertDialog.show(); dialog.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { if (null != getActivity()) { InputMethodManager imm = (InputMethodManager) getActivity() .getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(view.getApplicationWindowToken(), 0); } } }); final Button saveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE); saveButton.setEnabled(false); confirmNewPasswordText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { String oldPwd = oldPasswordText.getText().toString().trim(); String newPwd = newPasswordText.getText().toString().trim(); String newConfirmPwd = confirmNewPasswordText.getText().toString().trim(); saveButton.setEnabled((oldPwd.length() > 0) && (newPwd.length() > 0) && TextUtils.equals(newPwd, newConfirmPwd)); } @Override public void afterTextChanged(Editable s) { } }); } }); } /** * Update a push rule. */ private void onPushRuleClick(final String fResourceText, final boolean newValue) { final GcmRegistrationManager gcmMgr = Matrix.getInstance(getActivity()).getSharedGCMRegistrationManager(); Log.d(LOG_TAG, "onPushRuleClick " + fResourceText + " : set to " + newValue); if (fResourceText.equals(PreferencesManager.SETTINGS_TURN_SCREEN_ON_PREFERENCE_KEY)) { if (gcmMgr.isScreenTurnedOn() != newValue) { gcmMgr.setScreenTurnedOn(newValue); } return; } if (fResourceText.equals(PreferencesManager.SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY)) { boolean isConnected = Matrix.getInstance(getActivity()).isConnected(); final boolean isAllowed = gcmMgr.areDeviceNotificationsAllowed(); // avoid useless update if (isAllowed == newValue) { return; } gcmMgr.setDeviceNotificationsAllowed(!isAllowed); // when using GCM // need to register on servers if (isConnected && gcmMgr.useGCM() && (gcmMgr.isServerRegistred() || gcmMgr.isServerUnRegistred())) { final GcmRegistrationManager.ThirdPartyRegistrationListener listener = new GcmRegistrationManager.ThirdPartyRegistrationListener() { private void onDone() { if (null != getActivity()) { getActivity().runOnUiThread(new Runnable() { @Override public void run() { hideLoadingView(true); refreshPushersList(); } }); } } @Override public void onThirdPartyRegistered() { onDone(); } @Override public void onThirdPartyRegistrationFailed() { gcmMgr.setDeviceNotificationsAllowed(isAllowed); onDone(); } @Override public void onThirdPartyUnregistered() { onDone(); } @Override public void onThirdPartyUnregistrationFailed() { gcmMgr.setDeviceNotificationsAllowed(isAllowed); onDone(); } }; displayLoadingView(); if (gcmMgr.isServerRegistred()) { gcmMgr.unregister(listener); } else { gcmMgr.register(listener); } } return; } final String ruleId = mPushesRuleByResourceId.get(fResourceText); BingRule rule = mSession.getDataHandler().pushRules().findDefaultRule(ruleId); // check if there is an update boolean curValue = ((null != rule) && rule.isEnabled); if (TextUtils.equals(ruleId, BingRule.RULE_ID_DISABLE_ALL) || TextUtils.equals(ruleId, BingRule.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS)) { curValue = !curValue; } // on some old android APIs, // the callback is called even if there is no user interaction // so the value will be checked to ensure there is really no update. if (newValue == curValue) { return; } if (null != rule) { displayLoadingView(); mSession.getDataHandler().getBingRulesManager().updateEnableRuleStatus(rule, !rule.isEnabled, new BingRulesManager.onBingRuleUpdateListener() { private void onDone() { refreshDisplay(); hideLoadingView(); } @Override public void onBingRuleUpdateSuccess() { onDone(); } @Override public void onBingRuleUpdateFailure(String errorMessage) { if (null != getActivity()) { Toast.makeText(getActivity(), errorMessage, Toast.LENGTH_SHORT).show(); } onDone(); } }); } } /** * Update the displayname. */ private void onDisplayNameClick(final String value) { if (!TextUtils.equals(mSession.getMyUser().displayname, value)) { displayLoadingView(); mSession.getMyUser().updateDisplayName(value, new ApiCallback<Void>() { @Override public void onSuccess(Void info) { // refresh the settings value SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); SharedPreferences.Editor editor = preferences.edit(); editor.putString(PreferencesManager.SETTINGS_DISPLAY_NAME_PREFERENCE_KEY, value); editor.commit(); onCommonDone(null); refreshDisplay(); } @Override public void onNetworkError(Exception e) { onCommonDone(e.getLocalizedMessage()); } @Override public void onMatrixError(final MatrixError e) { if (MatrixError.M_CONSENT_NOT_GIVEN.equals(e.errcode)) { if (null != getActivity()) { getActivity().runOnUiThread(new Runnable() { @Override public void run() { hideLoadingView(); ((RiotAppCompatActivity) getActivity()).getConsentNotGivenHelper() .displayDialog(e); } }); } } else { onCommonDone(e.getLocalizedMessage()); } } @Override public void onUnexpectedError(Exception e) { onCommonDone(e.getLocalizedMessage()); } }); } } /** * Update the avatar. */ private void onUpdateAvatarClick() { getActivity().runOnUiThread(new Runnable() { @Override public void run() { if (CommonActivityUtils.checkPermissions(CommonActivityUtils.REQUEST_CODE_PERMISSION_TAKE_PHOTO, getActivity())) { Intent intent = new Intent(getActivity(), VectorMediasPickerActivity.class); intent.putExtra(VectorMediasPickerActivity.EXTRA_AVATAR_MODE, true); startActivityForResult(intent, VectorUtils.TAKE_IMAGE); } } }); } /** * Refresh the notification ring tone */ private void refreshNotificationRingTone() { EditTextPreference notificationRingTonePreference = (EditTextPreference) findPreference( PreferencesManager.SETTINGS_NOTIFICATION_RINGTONE_SELECTION_PREFERENCE_KEY); notificationRingTonePreference.setSummary(PreferencesManager.getNotificationRingToneName(getActivity())); } /** * Refresh the notification privacy setting */ private void refreshNotificationPrivacy() { EditTextPreference notificationPrivacyPreference = (EditTextPreference) findPreference( PreferencesManager.SETTINGS_NOTIFICATION_PRIVACY_PREFERENCE_KEY); if (notificationPrivacyPreference != null) { GcmRegistrationManager gcmRegistrationManager = Matrix.getInstance(getActivity()) .getSharedGCMRegistrationManager(); // this setting apply only with GCM for the moment if (gcmRegistrationManager.useGCM()) { String notificationPrivacyString = NotificationPrivacyActivity.getNotificationPrivacyString( getActivity().getApplicationContext(), gcmRegistrationManager.getNotificationPrivacy()); notificationPrivacyPreference.setSummary(notificationPrivacyString); } else { PreferenceCategory notificationsSettingsCategory = (PreferenceCategory) findPreference( PreferencesManager.SETTINGS_NOTIFICATIONS_KEY); notificationsSettingsCategory.removePreference(notificationPrivacyPreference); } } } @Override public void onActivityResult(int requestCode, int resultCode, final Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == Activity.RESULT_OK) { switch (requestCode) { case REQUEST_NOTIFICATION_RINGTONE: { PreferencesManager.setNotificationRingTone(getActivity(), (Uri) data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI)); // test if the selected ring tone can be played if (null == PreferencesManager.getNotificationRingToneName(getActivity())) { PreferencesManager.setNotificationRingTone(getActivity(), PreferencesManager.getNotificationRingTone(getActivity())); } refreshNotificationRingTone(); break; } case REQUEST_E2E_FILE_REQUEST_CODE: importKeys(data); break; case REQUEST_NEW_PHONE_NUMBER: refreshPhoneNumbersList(); break; case REQUEST_PHONEBOOK_COUNTRY: onPhonebookCountryUpdate(data); break; case REQUEST_LOCALE: startActivity(getActivity().getIntent()); getActivity().finish(); break; case VectorUtils.TAKE_IMAGE: Uri thumbnailUri = VectorUtils.getThumbnailUriFromIntent(getActivity(), data, mSession.getMediasCache()); if (null != thumbnailUri) { displayLoadingView(); ResourceUtils.Resource resource = ResourceUtils.openResource(getActivity(), thumbnailUri, null); if (null != resource) { mSession.getMediasCache().uploadContent(resource.mContentStream, null, resource.mMimeType, null, new MXMediaUploadListener() { @Override public void onUploadError(final String uploadId, final int serverResponseCode, final String serverErrorMessage) { getActivity().runOnUiThread(new Runnable() { @Override public void run() { onCommonDone(serverResponseCode + " : " + serverErrorMessage); } }); } @Override public void onUploadComplete(final String uploadId, final String contentUri) { getActivity().runOnUiThread(new Runnable() { @Override public void run() { mSession.getMyUser().updateAvatarUrl(contentUri, new ApiCallback<Void>() { @Override public void onSuccess(Void info) { onCommonDone(null); refreshDisplay(); } @Override public void onNetworkError(Exception e) { onCommonDone(e.getLocalizedMessage()); } @Override public void onMatrixError(final MatrixError e) { if (MatrixError.M_CONSENT_NOT_GIVEN .equals(e.errcode)) { if (null != getActivity()) { getActivity().runOnUiThread(new Runnable() { @Override public void run() { hideLoadingView(); ((RiotAppCompatActivity) getActivity()) .getConsentNotGivenHelper() .displayDialog(e); } }); } } else { onCommonDone(e.getLocalizedMessage()); } } @Override public void onUnexpectedError(Exception e) { onCommonDone(e.getLocalizedMessage()); } }); } }); } }); } } break; } } } /** * Refresh the known information about the account */ private void refreshPreferences() { final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); SharedPreferences.Editor editor = preferences.edit(); editor.putString(PreferencesManager.SETTINGS_DISPLAY_NAME_PREFERENCE_KEY, mSession.getMyUser().displayname); editor.putString(PreferencesManager.SETTINGS_VERSION_PREFERENCE_KEY, VectorUtils.getApplicationVersion(getActivity())); BingRuleSet mBingRuleSet = mSession.getDataHandler().pushRules(); if (null != mBingRuleSet) { for (String resourceText : mPushesRuleByResourceId.keySet()) { Preference preference = findPreference(resourceText); if ((null != preference) && (preference instanceof CheckBoxPreference)) { String ruleId = mPushesRuleByResourceId.get(resourceText); BingRule rule = mBingRuleSet.findDefaultRule(ruleId); boolean isEnabled = ((null != rule) && rule.isEnabled); if (TextUtils.equals(ruleId, BingRule.RULE_ID_DISABLE_ALL) || TextUtils.equals(ruleId, BingRule.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS)) { isEnabled = !isEnabled; } // check if the rule is only defined by don't notify else if (isEnabled) { List<Object> actions = rule.actions; // no action -> noting will be done if ((null == actions) || actions.isEmpty()) { isEnabled = false; } else if (1 == actions.size()) { try { isEnabled = !TextUtils.equals((String) (actions.get(0)), BingRule.ACTION_DONT_NOTIFY); } catch (Exception e) { Log.e(LOG_TAG, "## refreshPreferences failed " + e.getMessage()); } } } editor.putBoolean(resourceText, isEnabled); } } } editor.commit(); } /** * Display a dialog which asks confirmation for the deletion of a 3pid * * @param pid the 3pid to delete * @param preferenceSummary the displayed 3pid */ private void displayDelete3PIDConfirmationDialog(final ThirdPartyIdentifier pid, final CharSequence preferenceSummary) { final String mediumFriendlyName = ThreePid.getMediumFriendlyName(pid.medium, getActivity()) .toLowerCase(VectorApp.getApplicationLocale()); final String dialogMessage = getString(R.string.settings_delete_threepid_confirmation, mediumFriendlyName, preferenceSummary); new AlertDialog.Builder(getActivity()).setTitle(R.string.dialog_title_confirmation) .setMessage(dialogMessage) .setPositiveButton(R.string.remove, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); displayLoadingView(); mSession.getMyUser().delete3Pid(pid, new ApiCallback<Void>() { @Override public void onSuccess(Void info) { switch (pid.medium) { case ThreePid.MEDIUM_EMAIL: refreshEmailsList(); break; case ThreePid.MEDIUM_MSISDN: refreshPhoneNumbersList(); break; } onCommonDone(null); } @Override public void onNetworkError(Exception e) { onCommonDone(e.getLocalizedMessage()); } @Override public void onMatrixError(MatrixError e) { onCommonDone(e.getLocalizedMessage()); } @Override public void onUnexpectedError(Exception e) { onCommonDone(e.getLocalizedMessage()); } }); } }).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }).create().show(); } //============================================================================================================== // ignored users list management //============================================================================================================== /** * Refresh the ignored users list */ private void refreshIgnoredUsersList() { List<String> ignoredUsersList = mSession.getDataHandler().getIgnoredUserIds(); Collections.sort(ignoredUsersList, new Comparator<String>() { @Override public int compare(String u1, String u2) { return u1.toLowerCase(VectorApp.getApplicationLocale()) .compareTo(u2.toLowerCase(VectorApp.getApplicationLocale())); } }); PreferenceScreen preferenceScreen = getPreferenceScreen(); preferenceScreen.removePreference(mIgnoredUserSettingsCategory); preferenceScreen.removePreference(mIgnoredUserSettingsCategoryDivider); mIgnoredUserSettingsCategory.removeAll(); if (ignoredUsersList.size() > 0) { preferenceScreen.addPreference(mIgnoredUserSettingsCategoryDivider); preferenceScreen.addPreference(mIgnoredUserSettingsCategory); for (final String userId : ignoredUsersList) { VectorCustomActionEditTextPreference preference = new VectorCustomActionEditTextPreference( getActivity()); preference.setTitle(userId); preference.setKey(IGNORED_USER_KEY_BASE + userId); preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { new AlertDialog.Builder(getActivity()) .setMessage(getString(R.string.settings_unignore_user, userId)) .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); displayLoadingView(); ArrayList<String> idsList = new ArrayList<>(); idsList.add(userId); mSession.unIgnoreUsers(idsList, new ApiCallback<Void>() { @Override public void onSuccess(Void info) { onCommonDone(null); } @Override public void onNetworkError(Exception e) { onCommonDone(e.getLocalizedMessage()); } @Override public void onMatrixError(MatrixError e) { onCommonDone(e.getLocalizedMessage()); } @Override public void onUnexpectedError(Exception e) { onCommonDone(e.getLocalizedMessage()); } }); } }).setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }).create().show(); return false; } }); mIgnoredUserSettingsCategory.addPreference(preference); } } } //============================================================================================================== // pushers list management //============================================================================================================== /** * Refresh the pushers list */ private void refreshPushersList() { final GcmRegistrationManager gcmRegistrationManager = Matrix.getInstance(getActivity()) .getSharedGCMRegistrationManager(); final List<Pusher> pushersList = new ArrayList<>(gcmRegistrationManager.mPushersList); if (pushersList.isEmpty()) { getPreferenceScreen().removePreference(mPushersSettingsCategory); getPreferenceScreen().removePreference(mPushersSettingsDivider); return; } // check first if there is an update boolean isNewList = true; if ((null != mDisplayedPushers) && (pushersList.size() == mDisplayedPushers.size())) { isNewList = !mDisplayedPushers.containsAll(pushersList); } if (isNewList) { // remove the displayed one mPushersSettingsCategory.removeAll(); // add new emails list mDisplayedPushers = pushersList; int index = 0; for (final Pusher pusher : mDisplayedPushers) { if (null != pusher.lang) { boolean isThisDeviceTarget = TextUtils .equals(gcmRegistrationManager.getCurrentRegistrationToken(), pusher.pushkey); VectorCustomActionEditTextPreference preference = new VectorCustomActionEditTextPreference( getActivity(), isThisDeviceTarget ? Typeface.BOLD : Typeface.NORMAL); preference.setTitle(pusher.deviceDisplayName); preference.setSummary(pusher.appDisplayName); preference.setKey(PUSHER_PREFERENCE_KEY_BASE + index); index++; mPushersSettingsCategory.addPreference(preference); // the user cannot remove the self device target if (!isThisDeviceTarget) { preference.setOnPreferenceLongClickListener( new VectorCustomActionEditTextPreference.OnPreferenceLongClickListener() { @Override public boolean onPreferenceLongClick(Preference preference) { final String dialogMessage = getString( R.string.settings_delete_notification_targets_confirmation); new AlertDialog.Builder(getActivity()) .setTitle(R.string.dialog_title_confirmation) .setMessage(dialogMessage).setPositiveButton(R.string.remove, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); displayLoadingView(); gcmRegistrationManager.unregister(mSession, pusher, new ApiCallback<Void>() { @Override public void onSuccess(Void info) { refreshPushersList(); onCommonDone(null); } @Override public void onNetworkError( Exception e) { onCommonDone( e.getLocalizedMessage()); } @Override public void onMatrixError( MatrixError e) { onCommonDone( e.getLocalizedMessage()); } @Override public void onUnexpectedError( Exception e) { onCommonDone( e.getLocalizedMessage()); } }); } }) .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }) .create().show(); return true; } }); } } } } } //============================================================================================================== // Email management //============================================================================================================== /** * Refresh the emails list */ private void refreshEmailsList() { final List<ThirdPartyIdentifier> currentEmail3PID = new ArrayList<>(mSession.getMyUser().getlinkedEmails()); List<String> newEmailsList = new ArrayList<>(); for (ThirdPartyIdentifier identifier : currentEmail3PID) { newEmailsList.add(identifier.address); } // check first if there is an update boolean isNewList = true; if ((null != mDisplayedEmails) && (newEmailsList.size() == mDisplayedEmails.size())) { isNewList = !mDisplayedEmails.containsAll(newEmailsList); } if (isNewList) { // remove the displayed one for (int index = 0;; index++) { Preference preference = mUserSettingsCategory.findPreference(EMAIL_PREFERENCE_KEY_BASE + index); if (null != preference) { mUserSettingsCategory.removePreference(preference); } else { break; } } // add new emails list mDisplayedEmails = newEmailsList; int index = 0; final Preference addEmailBtn = mUserSettingsCategory.findPreference(ADD_EMAIL_PREFERENCE_KEY); // reported by GA if (null == addEmailBtn) { return; } int order = addEmailBtn.getOrder(); for (final ThirdPartyIdentifier email3PID : currentEmail3PID) { VectorCustomActionEditTextPreference preference = new VectorCustomActionEditTextPreference( getActivity()); preference.setTitle(getString(R.string.settings_email_address)); preference.setSummary(email3PID.address); preference.setKey(EMAIL_PREFERENCE_KEY_BASE + index); preference.setOrder(order); preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { displayDelete3PIDConfirmationDialog(email3PID, preference.getSummary()); return true; } }); preference.setOnPreferenceLongClickListener( new VectorCustomActionEditTextPreference.OnPreferenceLongClickListener() { @Override public boolean onPreferenceLongClick(Preference preference) { VectorUtils.copyToClipboard(getActivity(), email3PID.address); return true; } }); mUserSettingsCategory.addPreference(preference); index++; order++; } addEmailBtn.setOrder(order); } } /** * A request has been processed. * Display a toast if there is a an error message * * @param errorMessage the error message */ private void onCommonDone(final String errorMessage) { if (null != getActivity()) { getActivity().runOnUiThread(new Runnable() { @Override public void run() { if (!TextUtils.isEmpty(errorMessage)) { Toast.makeText(VectorApp.getInstance(), errorMessage, Toast.LENGTH_SHORT).show(); } hideLoadingView(); } }); } } /** * Attempt to add a new email to the account * * @param email the email to add. */ private void addEmail(String email) { // check first if the email syntax is valid if (TextUtils.isEmpty(email) || !android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches()) { Toast.makeText(getActivity(), getString(R.string.auth_invalid_email), Toast.LENGTH_SHORT).show(); return; } // check first if the email syntax is valid if (mDisplayedEmails.indexOf(email) >= 0) { Toast.makeText(getActivity(), getString(R.string.auth_email_already_defined), Toast.LENGTH_SHORT) .show(); return; } final ThreePid pid = new ThreePid(email, ThreePid.MEDIUM_EMAIL); displayLoadingView(); mSession.getMyUser().requestEmailValidationToken(pid, new ApiCallback<Void>() { @Override public void onSuccess(Void info) { if (null != getActivity()) { getActivity().runOnUiThread(new Runnable() { @Override public void run() { showEmailValidationDialog(pid); } }); } } @Override public void onNetworkError(Exception e) { onCommonDone(e.getLocalizedMessage()); } @Override public void onMatrixError(MatrixError e) { if (TextUtils.equals(MatrixError.THREEPID_IN_USE, e.errcode)) { onCommonDone(getString(R.string.account_email_already_used_error)); } else { onCommonDone(e.getLocalizedMessage()); } } @Override public void onUnexpectedError(Exception e) { onCommonDone(e.getLocalizedMessage()); } }); } /** * Show an email validation dialog to warn the user tho valid his email link. * * @param pid the used pid. */ private void showEmailValidationDialog(final ThreePid pid) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle(R.string.account_email_validation_title); builder.setMessage(R.string.account_email_validation_message); builder.setPositiveButton(R.string._continue, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); mSession.getMyUser().add3Pid(pid, true, new ApiCallback<Void>() { @Override public void onSuccess(Void info) { if (null != getActivity()) { getActivity().runOnUiThread(new Runnable() { @Override public void run() { hideLoadingView(); refreshEmailsList(); } }); } } @Override public void onNetworkError(Exception e) { onCommonDone(e.getLocalizedMessage()); } @Override public void onMatrixError(MatrixError e) { if (TextUtils.equals(e.errcode, MatrixError.THREEPID_AUTH_FAILED)) { if (null != getActivity()) { getActivity().runOnUiThread(new Runnable() { @Override public void run() { hideLoadingView(); Toast.makeText(getActivity(), getString(R.string.account_email_validation_error), Toast.LENGTH_SHORT).show(); } }); } } else { onCommonDone(e.getLocalizedMessage()); } } @Override public void onUnexpectedError(Exception e) { onCommonDone(e.getLocalizedMessage()); } }); } }); builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); hideLoadingView(); } }); AlertDialog alert = builder.create(); alert.show(); } //============================================================================================================== // Phone number management //============================================================================================================== /** * Refresh phone number list */ private void refreshPhoneNumbersList() { final List<ThirdPartyIdentifier> currentPhoneNumber3PID = new ArrayList<>( mSession.getMyUser().getlinkedPhoneNumbers()); List<String> phoneNumberList = new ArrayList<>(); for (ThirdPartyIdentifier identifier : currentPhoneNumber3PID) { phoneNumberList.add(identifier.address); } // check first if there is an update boolean isNewList = true; if ((null != mDisplayedPhoneNumber) && (phoneNumberList.size() == mDisplayedPhoneNumber.size())) { isNewList = !mDisplayedPhoneNumber.containsAll(phoneNumberList); } if (isNewList) { // remove the displayed one for (int index = 0;; index++) { Preference preference = mUserSettingsCategory .findPreference(PHONE_NUMBER_PREFERENCE_KEY_BASE + index); if (null != preference) { mUserSettingsCategory.removePreference(preference); } else { break; } } // add new phone number list mDisplayedPhoneNumber = phoneNumberList; int index = 0; final Preference addPhoneBtn = mUserSettingsCategory.findPreference(ADD_PHONE_NUMBER_PREFERENCE_KEY); int order = addPhoneBtn.getOrder(); for (final ThirdPartyIdentifier phoneNumber3PID : currentPhoneNumber3PID) { VectorCustomActionEditTextPreference preference = new VectorCustomActionEditTextPreference( getActivity()); preference.setTitle(getString(R.string.settings_phone_number)); String phoneNumberFormatted = phoneNumber3PID.address; try { // Attempt to format phone number final Phonenumber.PhoneNumber phoneNumber = PhoneNumberUtil.getInstance() .parse("+" + phoneNumberFormatted, null); phoneNumberFormatted = PhoneNumberUtil.getInstance().format(phoneNumber, PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL); } catch (NumberParseException e) { // Do nothing, we will display raw version } preference.setSummary(phoneNumberFormatted); preference.setKey(PHONE_NUMBER_PREFERENCE_KEY_BASE + index); preference.setOrder(order); preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { displayDelete3PIDConfirmationDialog(phoneNumber3PID, preference.getSummary()); return true; } }); preference.setOnPreferenceLongClickListener( new VectorCustomActionEditTextPreference.OnPreferenceLongClickListener() { @Override public boolean onPreferenceLongClick(Preference preference) { VectorUtils.copyToClipboard(getActivity(), phoneNumber3PID.address); return true; } }); index++; order++; mUserSettingsCategory.addPreference(preference); } addPhoneBtn.setOrder(order); } } //============================================================================================================== // contacts management //============================================================================================================== private void setContactsPreferences() { // Permission if (Build.VERSION.SDK_INT >= 23) { // on Android >= 23, use the system one mContactSettingsCategory.removePreference(findPreference(ContactsManager.CONTACTS_BOOK_ACCESS_KEY)); } // Phonebook country mContactPhonebookCountryPreference = (VectorCustomActionEditTextPreference) findPreference( PreferencesManager.SETTINGS_CONTACTS_PHONEBOOK_COUNTRY_PREFERENCE_KEY); mContactPhonebookCountryPreference .setSummary(PhoneNumberUtils.getHumanCountryCode(PhoneNumberUtils.getCountryCode(getActivity()))); mContactPhonebookCountryPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { Intent intent = CountryPickerActivity.getIntent(getActivity(), true); startActivityForResult(intent, REQUEST_PHONEBOOK_COUNTRY); return true; } }); } private void onPhonebookCountryUpdate(final Intent data) { if (data != null && data.hasExtra(CountryPickerActivity.EXTRA_OUT_COUNTRY_NAME) && data.hasExtra(CountryPickerActivity.EXTRA_OUT_COUNTRY_CODE)) { final String countryCode = data.getStringExtra(CountryPickerActivity.EXTRA_OUT_COUNTRY_CODE); if (!TextUtils.equals(countryCode, PhoneNumberUtils.getCountryCode(getActivity()))) { PhoneNumberUtils.setCountryCode(getActivity(), countryCode); mContactPhonebookCountryPreference .setSummary(data.getStringExtra(CountryPickerActivity.EXTRA_OUT_COUNTRY_NAME)); } } } //============================================================================================================== // user interface management //============================================================================================================== private void setUserInterfacePreferences() { VectorCustomActionEditTextPreference selectedLangaguePreference = (VectorCustomActionEditTextPreference) findPreference( PreferencesManager.SETTINGS_INTERFACE_LANGUAGE_PREFERENCE_KEY); selectedLangaguePreference.setSummary(VectorApp.localeToLocalisedString(VectorApp.getApplicationLocale())); selectedLangaguePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { startActivityForResult(LanguagePickerActivity.getIntent(getActivity()), REQUEST_LOCALE); return true; } }); VectorCustomActionEditTextPreference textSizePreference = (VectorCustomActionEditTextPreference) findPreference( PreferencesManager.SETTINGS_INTERFACE_TEXT_SIZE_KEY); textSizePreference.setSummary(VectorApp.getFontScaleDescription()); textSizePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { displayTextSizeSelection(getActivity()); return true; } }); } private void displayTextSizeSelection(final Activity activity) { AlertDialog.Builder builder = new AlertDialog.Builder(activity); LayoutInflater inflater = activity.getLayoutInflater(); View layout = inflater.inflate(R.layout.text_size_selection, null); builder.setTitle(R.string.font_size); builder.setView(layout); builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { } }); builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { } }); final AlertDialog dialog = builder.create(); dialog.show(); LinearLayout linearLayout = layout.findViewById(R.id.text_selection_group_view); int childCount = linearLayout.getChildCount(); String scaleText = VectorApp.getFontScale(); for (int i = 0; i < childCount; i++) { View v = linearLayout.getChildAt(i); if (v instanceof CheckedTextView) { final CheckedTextView checkedTextView = (CheckedTextView) v; checkedTextView.setChecked(TextUtils.equals(checkedTextView.getText(), scaleText)); checkedTextView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); VectorApp.updateFontScale(checkedTextView.getText().toString()); activity.startActivity(activity.getIntent()); activity.finish(); } }); } } } //============================================================================================================== // background sync management //============================================================================================================== /** * Convert a delay in seconds to string * * @param seconds the delay in seconds * @return the text */ private String secondsToText(int seconds) { if (seconds > 1) { return seconds + " " + getString(R.string.settings_seconds); } else { return seconds + " " + getString(R.string.settings_second); } } /** * Refresh the background sync preference */ private void refreshBackgroundSyncPrefs() { // sanity check if (null == getActivity()) { return; } final GcmRegistrationManager gcmmgr = Matrix.getInstance(getActivity()).getSharedGCMRegistrationManager(); final int timeout = gcmmgr.getBackgroundSyncTimeOut() / 1000; final int delay = gcmmgr.getBackgroundSyncDelay() / 1000; // update the settings final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); SharedPreferences.Editor editor = preferences.edit(); editor.putString(PreferencesManager.SETTINGS_SET_SYNC_TIMEOUT_PREFERENCE_KEY, timeout + ""); editor.putString(PreferencesManager.SETTINGS_SET_SYNC_DELAY_PREFERENCE_KEY, delay + ""); editor.commit(); if (null != mSyncRequestTimeoutPreference) { mSyncRequestTimeoutPreference.setSummary(secondsToText(timeout)); mSyncRequestTimeoutPreference.setText(timeout + ""); mSyncRequestTimeoutPreference .setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { int newTimeOut = timeout; try { newTimeOut = Integer.parseInt((String) newValue); } catch (Exception e) { Log.e(LOG_TAG, "## refreshBackgroundSyncPrefs : parseInt failed " + e.getMessage()); } if (newTimeOut != timeout) { gcmmgr.setBackgroundSyncTimeOut(newTimeOut * 1000); getActivity().runOnUiThread(new Runnable() { @Override public void run() { refreshBackgroundSyncPrefs(); } }); } return false; } }); } if (null != mSyncRequestDelayPreference) { mSyncRequestDelayPreference.setSummary(secondsToText(delay)); mSyncRequestDelayPreference.setText(delay + ""); mSyncRequestDelayPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { int newDelay = delay; try { newDelay = Integer.parseInt((String) newValue); } catch (Exception e) { Log.e(LOG_TAG, "## refreshBackgroundSyncPrefs : parseInt failed " + e.getMessage()); } if (newDelay != delay) { gcmmgr.setBackgroundSyncDelay(newDelay * 1000); getActivity().runOnUiThread(new Runnable() { @Override public void run() { refreshBackgroundSyncPrefs(); } }); } return false; } }); } } //============================================================================================================== // Cryptography //============================================================================================================== private void removeCryptographyPreference() { PreferenceScreen preferenceScreen; if (null != (preferenceScreen = getPreferenceScreen())) { preferenceScreen.removePreference(mCryptographyCategory); preferenceScreen.removePreference(mCryptographyCategoryDivider); } } /** * Build the cryptography preference section. * * @param aMyDeviceInfo the device info */ private void refreshCryptographyPreference(final DeviceInfo aMyDeviceInfo) { final String userId = mSession.getMyUserId(); final String deviceId = mSession.getCredentials().deviceId; VectorCustomActionEditTextPreference cryptoInfoTextPreference; // device name if ((null != aMyDeviceInfo) && !TextUtils.isEmpty(aMyDeviceInfo.display_name)) { cryptoInfoTextPreference = (VectorCustomActionEditTextPreference) findPreference( PreferencesManager.SETTINGS_ENCRYPTION_INFORMATION_DEVICE_NAME_PREFERENCE_KEY); if (null != cryptoInfoTextPreference) { cryptoInfoTextPreference.setSummary(aMyDeviceInfo.display_name); cryptoInfoTextPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { displayDeviceRenameDialog(aMyDeviceInfo); return true; } }); cryptoInfoTextPreference.setOnPreferenceLongClickListener( new VectorCustomActionEditTextPreference.OnPreferenceLongClickListener() { @Override public boolean onPreferenceLongClick(Preference preference) { VectorUtils.copyToClipboard(getActivity(), aMyDeviceInfo.display_name); return true; } }); } } // crypto section: device ID if (!TextUtils.isEmpty(deviceId)) { cryptoInfoTextPreference = (VectorCustomActionEditTextPreference) findPreference( PreferencesManager.SETTINGS_ENCRYPTION_INFORMATION_DEVICE_ID_PREFERENCE_KEY); if (null != cryptoInfoTextPreference) { cryptoInfoTextPreference.setSummary(deviceId); cryptoInfoTextPreference.setOnPreferenceLongClickListener( new VectorCustomActionEditTextPreference.OnPreferenceLongClickListener() { @Override public boolean onPreferenceLongClick(Preference preference) { VectorUtils.copyToClipboard(getActivity(), deviceId); return true; } }); } VectorCustomActionEditTextPreference exportPref = (VectorCustomActionEditTextPreference) findPreference( PreferencesManager.SETTINGS_ENCRYPTION_EXPORT_E2E_ROOM_KEYS_PREFERENCE_KEY); exportPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { exportKeys(); return true; } }); VectorCustomActionEditTextPreference importPref = (VectorCustomActionEditTextPreference) findPreference( PreferencesManager.SETTINGS_ENCRYPTION_IMPORT_E2E_ROOM_KEYS_PREFERENCE_KEY); importPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { importKeys(); return true; } }); } // crypto section: device key (fingerprint) if (!TextUtils.isEmpty(deviceId) && !TextUtils.isEmpty(userId)) { mSession.getCrypto().getDeviceInfo(userId, deviceId, new SimpleApiCallback<MXDeviceInfo>() { @Override public void onSuccess(final MXDeviceInfo deviceInfo) { if ((null != deviceInfo) && !TextUtils.isEmpty(deviceInfo.fingerprint()) && (null != getActivity())) { VectorCustomActionEditTextPreference cryptoInfoTextPreference = (VectorCustomActionEditTextPreference) findPreference( PreferencesManager.SETTINGS_ENCRYPTION_INFORMATION_DEVICE_KEY_PREFERENCE_KEY); if (null != cryptoInfoTextPreference) { cryptoInfoTextPreference.setSummary(deviceInfo.fingerprint()); cryptoInfoTextPreference.setOnPreferenceLongClickListener( new VectorCustomActionEditTextPreference.OnPreferenceLongClickListener() { @Override public boolean onPreferenceLongClick(Preference preference) { VectorUtils.copyToClipboard(getActivity(), deviceInfo.fingerprint()); return true; } }); } } } }); } // encrypt to unverified devices final CheckBoxPreference sendToUnverifiedDevicesPref = (CheckBoxPreference) findPreference( PreferencesManager.SETTINGS_ENCRYPTION_NEVER_SENT_TO_PREFERENCE_KEY); if (null != sendToUnverifiedDevicesPref) { sendToUnverifiedDevicesPref.setChecked(false); mSession.getCrypto().getGlobalBlacklistUnverifiedDevices(new SimpleApiCallback<Boolean>() { @Override public void onSuccess(Boolean status) { sendToUnverifiedDevicesPref.setChecked(status); } }); sendToUnverifiedDevicesPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { mSession.getCrypto().getGlobalBlacklistUnverifiedDevices(new SimpleApiCallback<Boolean>() { @Override public void onSuccess(Boolean status) { if (sendToUnverifiedDevicesPref.isChecked() != status) { mSession.getCrypto().setGlobalBlacklistUnverifiedDevices( sendToUnverifiedDevicesPref.isChecked(), new SimpleApiCallback<Void>() { @Override public void onSuccess(Void info) { } }); } } }); return true; } }); } } //============================================================================================================== // devices list //============================================================================================================== private void removeDevicesPreference() { PreferenceScreen preferenceScreen; if (null != (preferenceScreen = getPreferenceScreen())) { preferenceScreen.removePreference(mDevicesListSettingsCategory); preferenceScreen.removePreference(mDevicesListSettingsCategoryDivider); } } /** * Force the refresh of the devices list.<br> * The devices list is the list of the devices where the user as looged in. * It can be any mobile device, as any browser. */ private void refreshDevicesList() { if ((null != mSession) && (mSession.isCryptoEnabled()) && (!TextUtils.isEmpty(mSession.getCredentials().deviceId))) { // display a spinner while loading the devices list if (0 == mDevicesListSettingsCategory.getPreferenceCount()) { ProgressBarPreference preference = new ProgressBarPreference(getActivity()); mDevicesListSettingsCategory.addPreference(preference); } mSession.getDevicesList(new ApiCallback<DevicesListResponse>() { @Override public void onSuccess(DevicesListResponse info) { if (0 == info.devices.size()) { removeDevicesPreference(); } else { buildDevicesSettings(info.devices); } } @Override public void onNetworkError(Exception e) { removeDevicesPreference(); onCommonDone(e.getMessage()); } @Override public void onMatrixError(MatrixError e) { removeDevicesPreference(); onCommonDone(e.getMessage()); } @Override public void onUnexpectedError(Exception e) { removeDevicesPreference(); onCommonDone(e.getMessage()); } }); } else { removeDevicesPreference(); removeCryptographyPreference(); } } /** * Build the devices portion of the settings.<br> * Each row correspond to a device ID and its corresponding device name. Clicking on the row * display a dialog containing: the device ID, the device name and the "last seen" information. * * @param aDeviceInfoList the list of the devices */ private void buildDevicesSettings(List<DeviceInfo> aDeviceInfoList) { VectorCustomActionEditTextPreference preference; int typeFaceHighlight; boolean isNewList = true; String myDeviceId = mSession.getCredentials().deviceId; if ((null != mDevicesNameList) && (aDeviceInfoList.size() == mDevicesNameList.size())) { isNewList = !mDevicesNameList.containsAll(aDeviceInfoList); } if (isNewList) { int prefIndex = 0; mDevicesNameList = aDeviceInfoList; // sort before display: most recent first DeviceInfo.sortByLastSeen(mDevicesNameList); // start from scratch: remove the displayed ones mDevicesListSettingsCategory.removeAll(); for (DeviceInfo deviceInfo : mDevicesNameList) { // set bold to distinguish current device ID if ((null != myDeviceId) && myDeviceId.equals(deviceInfo.device_id)) { mMyDeviceInfo = deviceInfo; typeFaceHighlight = Typeface.BOLD; } else { typeFaceHighlight = Typeface.NORMAL; } // add the edit text preference preference = new VectorCustomActionEditTextPreference(getActivity(), typeFaceHighlight); if ((null == deviceInfo.device_id) && (null == deviceInfo.display_name)) { continue; } else { if (null != deviceInfo.device_id) { preference.setTitle(deviceInfo.device_id); } // display name parameter can be null (new JSON API) if (null != deviceInfo.display_name) { preference.setSummary(deviceInfo.display_name); } } preference.setKey(DEVICES_PREFERENCE_KEY_BASE + prefIndex); prefIndex++; // onClick handler: display device details dialog final DeviceInfo fDeviceInfo = deviceInfo; preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { displayDeviceDetailsDialog(fDeviceInfo); return true; } }); mDevicesListSettingsCategory.addPreference(preference); } refreshCryptographyPreference(mMyDeviceInfo); } } /** * Display a dialog containing the device ID, the device name and the "last seen" information.<> * This dialog allow to delete the corresponding device (see {@link #displayDeviceDeletionDialog(DeviceInfo)}) * * @param aDeviceInfo the device information */ private void displayDeviceDetailsDialog(DeviceInfo aDeviceInfo) { android.support.v7.app.AlertDialog.Builder builder = new android.support.v7.app.AlertDialog.Builder( getActivity()); LayoutInflater inflater = getActivity().getLayoutInflater(); View layout = inflater.inflate(R.layout.devices_details_settings, null); if (null != aDeviceInfo) { //device ID TextView textView = layout.findViewById(R.id.device_id); textView.setText(aDeviceInfo.device_id); // device name textView = layout.findViewById(R.id.device_name); String displayName = (TextUtils.isEmpty(aDeviceInfo.display_name)) ? LABEL_UNAVAILABLE_DATA : aDeviceInfo.display_name; textView.setText(displayName); // last seen info textView = layout.findViewById(R.id.device_last_seen); if (!TextUtils.isEmpty(aDeviceInfo.last_seen_ip)) { String lastSeenIp = aDeviceInfo.last_seen_ip; String lastSeenTime = LABEL_UNAVAILABLE_DATA; if (null != getActivity()) { SimpleDateFormat dateFormatTime = new SimpleDateFormat( getString(R.string.devices_details_time_format)); String time = dateFormatTime.format(new Date(aDeviceInfo.last_seen_ts)); DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault()); lastSeenTime = dateFormat.format(new Date(aDeviceInfo.last_seen_ts)) + ", " + time; } String lastSeenInfo = this.getString(R.string.devices_details_last_seen_format, lastSeenIp, lastSeenTime); textView.setText(lastSeenInfo); } else { // hide last time seen section layout.findViewById(R.id.device_last_seen_title).setVisibility(View.GONE); textView.setVisibility(View.GONE); } // title & icon builder.setTitle(R.string.devices_details_dialog_title); builder.setIcon(android.R.drawable.ic_dialog_info); builder.setView(layout); final DeviceInfo fDeviceInfo = aDeviceInfo; builder.setPositiveButton(R.string.rename, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { displayDeviceRenameDialog(fDeviceInfo); } }); // disable the deletion for our own device if (!TextUtils.equals(mSession.getCrypto().getMyDevice().deviceId, fDeviceInfo.device_id)) { builder.setNegativeButton(R.string.delete, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { displayDeviceDeletionDialog(fDeviceInfo); } }); } builder.setNeutralButton(R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); builder.setOnKeyListener(new DialogInterface.OnKeyListener() { @Override public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) { dialog.cancel(); return true; } return false; } }); builder.create().show(); } else { Log.e(LOG_TAG, "## displayDeviceDetailsDialog(): sanity check failure"); if (null != getActivity()) CommonActivityUtils.displayToast(getActivity().getApplicationContext(), "DeviceDetailsDialog cannot be displayed.\nBad input parameters."); } } /** * Display an alert dialog to rename a device * * @param aDeviceInfoToRename device info */ private void displayDeviceRenameDialog(final DeviceInfo aDeviceInfoToRename) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle(R.string.devices_details_device_name); final EditText input = new EditText(getActivity()); input.setText(aDeviceInfoToRename.display_name); builder.setView(input); builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { displayLoadingView(); mSession.setDeviceName(aDeviceInfoToRename.device_id, input.getText().toString(), new ApiCallback<Void>() { @Override public void onSuccess(Void info) { // search which preference is updated int count = mDevicesListSettingsCategory.getPreferenceCount(); for (int i = 0; i < count; i++) { VectorCustomActionEditTextPreference pref = (VectorCustomActionEditTextPreference) mDevicesListSettingsCategory .getPreference(i); if (TextUtils.equals(aDeviceInfoToRename.device_id, pref.getTitle())) { pref.setSummary(input.getText()); } } // detect if the updated device is the current account one Preference pref = findPreference( PreferencesManager.SETTINGS_ENCRYPTION_INFORMATION_DEVICE_ID_PREFERENCE_KEY); if (TextUtils.equals(pref.getSummary(), aDeviceInfoToRename.device_id)) { findPreference( PreferencesManager.SETTINGS_ENCRYPTION_INFORMATION_DEVICE_ID_PREFERENCE_KEY) .setSummary(input.getText()); } hideLoadingView(); } @Override public void onNetworkError(Exception e) { onCommonDone(e.getLocalizedMessage()); } @Override public void onMatrixError(MatrixError e) { onCommonDone(e.getLocalizedMessage()); } @Override public void onUnexpectedError(Exception e) { onCommonDone(e.getLocalizedMessage()); } }); } }); builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }); builder.show(); } /** * Try to delete a device. * * @param deviceId the device id */ private void deleteDevice(final String deviceId) { displayLoadingView(); mSession.deleteDevice(deviceId, mAccountPassword, new ApiCallback<Void>() { @Override public void onSuccess(Void info) { hideLoadingView(); refreshDevicesList(); // force settings update } private void onError(String message) { mAccountPassword = null; onCommonDone(message); } @Override public void onNetworkError(Exception e) { onError(e.getLocalizedMessage()); } @Override public void onMatrixError(MatrixError e) { onError(e.getLocalizedMessage()); } @Override public void onUnexpectedError(Exception e) { onError(e.getLocalizedMessage()); } }); } /** * Display a delete confirmation dialog to remove a device.<br> * The user is invited to enter his password to confirm the deletion. * * @param aDeviceInfoToDelete device info */ private void displayDeviceDeletionDialog(final DeviceInfo aDeviceInfoToDelete) { if ((null != aDeviceInfoToDelete) && (null != aDeviceInfoToDelete.device_id)) { if (!TextUtils.isEmpty(mAccountPassword)) { deleteDevice(aDeviceInfoToDelete.device_id); } else { android.support.v7.app.AlertDialog.Builder builder = new android.support.v7.app.AlertDialog.Builder( getActivity()); LayoutInflater inflater = getActivity().getLayoutInflater(); View layout = inflater.inflate(R.layout.devices_settings_delete, null); final EditText passwordEditText = layout.findViewById(R.id.delete_password); builder.setIcon(android.R.drawable.ic_dialog_alert); builder.setTitle(R.string.devices_delete_dialog_title); builder.setView(layout); builder.setPositiveButton(R.string.devices_delete_submit_button_label, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (null != mSession) { if (TextUtils.isEmpty(passwordEditText.toString())) { CommonActivityUtils.displayToast(VectorSettingsPreferencesFragment.this .getActivity().getApplicationContext(), "Password missing.."); return; } mAccountPassword = passwordEditText.getText().toString(); deleteDevice(aDeviceInfoToDelete.device_id); } } }); builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); hideLoadingView(); } }); builder.setOnKeyListener(new DialogInterface.OnKeyListener() { @Override public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) { dialog.cancel(); hideLoadingView(); return true; } return false; } }); builder.create().show(); } } else { Log.e(LOG_TAG, "## displayDeviceDeletionDialog(): sanity check failure"); } } /** * Manage the e2e keys export. */ private void exportKeys() { View dialogLayout = getActivity().getLayoutInflater().inflate(R.layout.dialog_export_e2e_keys, null); AlertDialog.Builder dialog = new AlertDialog.Builder(getActivity()); dialog.setTitle(R.string.encryption_export_room_keys); dialog.setView(dialogLayout); final TextInputEditText passPhrase1EditText = dialogLayout .findViewById(R.id.dialog_e2e_keys_passphrase_edit_text); final TextInputEditText passPhrase2EditText = dialogLayout .findViewById(R.id.dialog_e2e_keys_confirm_passphrase_edit_text); final Button exportButton = dialogLayout.findViewById(R.id.dialog_e2e_keys_export_button); final TextWatcher textWatcher = new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { exportButton.setEnabled(!TextUtils.isEmpty(passPhrase1EditText.getText()) && TextUtils.equals(passPhrase1EditText.getText(), passPhrase2EditText.getText())); } @Override public void afterTextChanged(Editable s) { } }; passPhrase1EditText.addTextChangedListener(textWatcher); passPhrase2EditText.addTextChangedListener(textWatcher); exportButton.setEnabled(false); final AlertDialog exportDialog = dialog.show(); exportButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { displayLoadingView(); CommonActivityUtils.exportKeys(mSession, passPhrase1EditText.getText().toString(), new ApiCallback<String>() { @Override public void onSuccess(String filename) { Toast.makeText(VectorApp.getInstance().getApplicationContext(), filename, Toast.LENGTH_SHORT).show(); hideLoadingView(); } @Override public void onNetworkError(Exception e) { hideLoadingView(); } @Override public void onMatrixError(MatrixError e) { hideLoadingView(); } @Override public void onUnexpectedError(Exception e) { hideLoadingView(); } }); exportDialog.dismiss(); } }); } /** * Manage the e2e keys import. */ @SuppressLint("NewApi") private void importKeys() { Intent fileIntent = new Intent(Intent.ACTION_GET_CONTENT); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { fileIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, false); } fileIntent.setType("*/*"); startActivityForResult(fileIntent, REQUEST_E2E_FILE_REQUEST_CODE); } /** * Manage the e2e keys import. * * @param intent the intent result */ private void importKeys(Intent intent) { // sanity check if (null == intent) { return; } ArrayList<RoomMediaMessage> sharedDataItems = new ArrayList<>( RoomMediaMessage.listRoomMediaMessages(intent)); if (sharedDataItems.size() > 0) { final RoomMediaMessage sharedDataItem = sharedDataItems.get(0); View dialogLayout = getActivity().getLayoutInflater().inflate(R.layout.dialog_import_e2e_keys, null); AlertDialog.Builder dialog = new AlertDialog.Builder(getActivity()); dialog.setTitle(R.string.encryption_import_room_keys); dialog.setView(dialogLayout); final TextInputEditText passPhraseEditText = dialogLayout .findViewById(R.id.dialog_e2e_keys_passphrase_edit_text); final Button importButton = dialogLayout.findViewById(R.id.dialog_e2e_keys_import_button); passPhraseEditText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { importButton.setEnabled(!TextUtils.isEmpty(passPhraseEditText.getText())); } @Override public void afterTextChanged(Editable s) { } }); importButton.setEnabled(false); final AlertDialog importDialog = dialog.show(); final Context appContext = getActivity().getApplicationContext(); importButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String password = passPhraseEditText.getText().toString(); final ResourceUtils.Resource resource = ResourceUtils.openResource(appContext, sharedDataItem.getUri(), sharedDataItem.getMimeType(appContext)); byte[] data; try { data = new byte[resource.mContentStream.available()]; resource.mContentStream.read(data); resource.mContentStream.close(); } catch (Exception e) { try { resource.mContentStream.close(); } catch (Exception e2) { Log.e(LOG_TAG, "## importKeys() : " + e2.getMessage()); } Toast.makeText(appContext, e.getLocalizedMessage(), Toast.LENGTH_SHORT).show(); return; } displayLoadingView(); mSession.getCrypto().importRoomKeys(data, password, new ApiCallback<Void>() { @Override public void onSuccess(Void info) { hideLoadingView(); } @Override public void onNetworkError(Exception e) { Toast.makeText(appContext, e.getLocalizedMessage(), Toast.LENGTH_SHORT).show(); hideLoadingView(); } @Override public void onMatrixError(MatrixError e) { Toast.makeText(appContext, e.getLocalizedMessage(), Toast.LENGTH_SHORT).show(); hideLoadingView(); } @Override public void onUnexpectedError(Exception e) { Toast.makeText(appContext, e.getLocalizedMessage(), Toast.LENGTH_SHORT).show(); hideLoadingView(); } }); importDialog.dismiss(); } }); } } //============================================================================================================== // Group flairs management //============================================================================================================== /** * Force the refresh of the devices list.<br> * The devices list is the list of the devices where the user as looged in. * It can be any mobile device, as any browser. */ private void refreshGroupFlairsList() { if (null != mSession) { // display a spinner while refreshing if (0 == mGroupsFlairCategory.getPreferenceCount()) { ProgressBarPreference preference = new ProgressBarPreference(getActivity()); mGroupsFlairCategory.addPreference(preference); } mSession.getGroupsManager().getUserPublicisedGroups(mSession.getMyUserId(), true, new ApiCallback<Set<String>>() { @Override public void onSuccess(Set<String> publicisedGroups) { buildGroupsList(publicisedGroups); } @Override public void onNetworkError(Exception e) { // NOP } @Override public void onMatrixError(MatrixError e) { // NOP } @Override public void onUnexpectedError(Exception e) { // NOP } }); } } // current publicised group list private Set<String> mPublicisedGroups = null; /** * Build the groups list. * * @param publicisedGroups the publicised groups list. */ private void buildGroupsList(final Set<String> publicisedGroups) { boolean isNewList = true; if ((null != mPublicisedGroups) && (mPublicisedGroups.size() == publicisedGroups.size())) { isNewList = !mPublicisedGroups.containsAll(publicisedGroups); } if (isNewList) { List<Group> joinedGroups = new ArrayList<>(mSession.getGroupsManager().getJoinedGroups()); Collections.sort(joinedGroups, Group.mGroupsComparator); int prefIndex = 0; mPublicisedGroups = publicisedGroups; // clear everything mGroupsFlairCategory.removeAll(); for (final Group group : joinedGroups) { final VectorGroupPreference vectorGroupPreference = new VectorGroupPreference(getActivity()); vectorGroupPreference.setKey(DEVICES_PREFERENCE_KEY_BASE + prefIndex); prefIndex++; vectorGroupPreference.setGroup(group, mSession); vectorGroupPreference.setTitle(group.getDisplayName()); vectorGroupPreference.setSummary(group.getGroupId()); vectorGroupPreference.setChecked(publicisedGroups.contains(group.getGroupId())); mGroupsFlairCategory.addPreference(vectorGroupPreference); vectorGroupPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValueAsVoid) { if (newValueAsVoid instanceof Boolean) { final boolean newValue = (boolean) newValueAsVoid; boolean isFlaired = mPublicisedGroups.contains(group.getGroupId()); if (newValue != isFlaired) { displayLoadingView(); mSession.getGroupsManager().updateGroupPublicity(group.getGroupId(), newValue, new ApiCallback<Void>() { @Override public void onSuccess(Void info) { hideLoadingView(); if (newValue) { mPublicisedGroups.add(group.getGroupId()); } else { mPublicisedGroups.remove(group.getGroupId()); } } private void onError() { hideLoadingView(); // restore default value vectorGroupPreference .setChecked(publicisedGroups.contains(group.getGroupId())); } @Override public void onNetworkError(Exception e) { onError(); } @Override public void onMatrixError(MatrixError e) { onError(); } @Override public void onUnexpectedError(Exception e) { onError(); } }); } } return true; } }); } refreshCryptographyPreference(mMyDeviceInfo); } } }