mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-22 18:00:02 +01:00
Add trim conversations by time option.
This commit is contained in:
@@ -1,35 +1,69 @@
|
||||
package org.thoughtcrime.securesms.preferences;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.preference.EditTextPreference;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.components.settings.BaseSettingsAdapter;
|
||||
import org.thoughtcrime.securesms.components.settings.BaseSettingsFragment;
|
||||
import org.thoughtcrime.securesms.components.settings.CustomizableSingleSelectSetting;
|
||||
import org.thoughtcrime.securesms.components.settings.SingleSelectSetting;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.keyvalue.KeepMessagesDuration;
|
||||
import org.thoughtcrime.securesms.keyvalue.SettingsValues;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.mediaoverview.MediaOverviewActivity;
|
||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
import org.thoughtcrime.securesms.preferences.widgets.StoragePreferenceCategory;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Trimmer;
|
||||
import org.thoughtcrime.securesms.util.MappingModelList;
|
||||
import org.thoughtcrime.securesms.util.StringUtil;
|
||||
import org.thoughtcrime.securesms.util.concurrent.SignalExecutors;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
|
||||
public class StoragePreferenceFragment extends ListSummaryPreferenceFragment {
|
||||
|
||||
private static final String TAG = Log.tag(StoragePreferenceFragment.class);
|
||||
private Preference keepMessages;
|
||||
private Preference trimLength;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle paramBundle) {
|
||||
public void onCreate(@Nullable Bundle paramBundle) {
|
||||
super.onCreate(paramBundle);
|
||||
|
||||
findPreference(TextSecurePreferences.THREAD_TRIM_NOW)
|
||||
.setOnPreferenceClickListener(new TrimNowClickListener());
|
||||
findPreference(TextSecurePreferences.THREAD_TRIM_LENGTH)
|
||||
.setOnPreferenceChangeListener(new TrimLengthValidationListener());
|
||||
findPreference("pref_storage_clear_message_history")
|
||||
.setOnPreferenceClickListener(new ClearMessageHistoryClickListener());
|
||||
|
||||
trimLength = findPreference(SettingsValues.THREAD_TRIM_LENGTH);
|
||||
trimLength.setOnPreferenceClickListener(p -> {
|
||||
getApplicationPreferencesActivity().requireSupportActionBar().setTitle(R.string.preferences__conversation_length_limit);
|
||||
getApplicationPreferencesActivity().pushFragment(BaseSettingsFragment.create(new ConversationLengthLimitConfiguration()));
|
||||
return true;
|
||||
});
|
||||
|
||||
keepMessages = findPreference(SettingsValues.KEEP_MESSAGES_DURATION);
|
||||
keepMessages.setOnPreferenceClickListener(p -> {
|
||||
getApplicationPreferencesActivity().requireSupportActionBar().setTitle(R.string.preferences__keep_messages);
|
||||
getApplicationPreferencesActivity().pushFragment(BaseSettingsFragment.create(new KeepMessagesConfiguration()));
|
||||
return true;
|
||||
});
|
||||
|
||||
StoragePreferenceCategory storageCategory = (StoragePreferenceCategory) findPreference("pref_storage_category");
|
||||
FragmentActivity activity = requireActivity();
|
||||
@@ -41,19 +75,24 @@ public class StoragePreferenceFragment extends ListSummaryPreferenceFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) {
|
||||
public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
|
||||
addPreferencesFromResource(R.xml.preferences_storage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
((ApplicationPreferencesActivity)getActivity()).getSupportActionBar().setTitle(R.string.preferences__storage);
|
||||
((ApplicationPreferencesActivity) requireActivity()).requireSupportActionBar().setTitle(R.string.preferences__storage);
|
||||
|
||||
FragmentActivity activity = requireActivity();
|
||||
ApplicationPreferencesViewModel viewModel = ApplicationPreferencesViewModel.getApplicationPreferencesViewModel(activity);
|
||||
|
||||
viewModel.refreshStorageBreakdown(activity.getApplicationContext());
|
||||
|
||||
keepMessages.setSummary(SignalStore.settings().getKeepMessagesDuration().getStringResource());
|
||||
|
||||
trimLength.setSummary(SignalStore.settings().isTrimByLengthEnabled() ? getString(R.string.preferences_storage__s_messages, NumberFormat.getInstance().format(SignalStore.settings().getThreadTrimLength()))
|
||||
: getString(R.string.preferences_storage__none));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -61,49 +100,197 @@ public class StoragePreferenceFragment extends ListSummaryPreferenceFragment {
|
||||
Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
|
||||
}
|
||||
|
||||
private class TrimNowClickListener implements Preference.OnPreferenceClickListener {
|
||||
private @NonNull ApplicationPreferencesActivity getApplicationPreferencesActivity() {
|
||||
return (ApplicationPreferencesActivity) requireActivity();
|
||||
}
|
||||
|
||||
private class ClearMessageHistoryClickListener implements Preference.OnPreferenceClickListener {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
final int threadLengthLimit = TextSecurePreferences.getThreadTrimLength(getActivity());
|
||||
public boolean onPreferenceClick(@NonNull Preference preference) {
|
||||
new AlertDialog.Builder(requireActivity())
|
||||
.setTitle(R.string.ApplicationPreferencesActivity_delete_all_old_messages_now)
|
||||
.setMessage(getResources().getQuantityString(R.plurals.ApplicationPreferencesActivity_this_will_immediately_trim_all_conversations_to_the_d_most_recent_messages,
|
||||
threadLengthLimit, threadLengthLimit))
|
||||
.setPositiveButton(R.string.ApplicationPreferencesActivity_delete, (dialog, which) -> Trimmer.trimAllThreads(getActivity(), threadLengthLimit))
|
||||
.setTitle(R.string.preferences_storage__clear_message_history)
|
||||
.setMessage(R.string.preferences_storage__this_will_delete_all_message_history_and_media_from_your_device)
|
||||
.setPositiveButton(R.string.delete, (d, w) -> showAreYouReallySure())
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void showAreYouReallySure() {
|
||||
new AlertDialog.Builder(requireActivity())
|
||||
.setTitle(R.string.preferences_storage__are_you_sure_you_want_to_delete_all_message_history)
|
||||
.setMessage(R.string.preferences_storage__all_message_history_will_be_permanently_removed_this_action_cannot_be_undone)
|
||||
.setPositiveButton(R.string.preferences_storage__delete_all_now, (d, w) -> SignalExecutors.BOUNDED.execute(() -> DatabaseFactory.getThreadDatabase(ApplicationDependencies.getApplication()).deleteAllConversations()))
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
private class TrimLengthValidationListener implements Preference.OnPreferenceChangeListener {
|
||||
public static class KeepMessagesConfiguration extends BaseSettingsFragment.Configuration implements SingleSelectSetting.SingleSelectSelectionChangedListener {
|
||||
|
||||
TrimLengthValidationListener() {
|
||||
EditTextPreference preference = (EditTextPreference)findPreference(TextSecurePreferences.THREAD_TRIM_LENGTH);
|
||||
onPreferenceChange(preference, preference.getText());
|
||||
@Override
|
||||
public void configureAdapter(@NonNull BaseSettingsAdapter adapter) {
|
||||
adapter.configureSingleSelect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
if (newValue == null || ((String)newValue).trim().length() == 0) {
|
||||
return false;
|
||||
public @NonNull MappingModelList getSettings() {
|
||||
KeepMessagesDuration currentDuration = SignalStore.settings().getKeepMessagesDuration();
|
||||
return Stream.of(KeepMessagesDuration.values())
|
||||
.map(duration -> new SingleSelectSetting.Item(duration, activity.getString(duration.getStringResource()), duration.equals(currentDuration)))
|
||||
.collect(MappingModelList.toMappingModelList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelectionChanged(@NonNull Object selection) {
|
||||
KeepMessagesDuration currentDuration = SignalStore.settings().getKeepMessagesDuration();
|
||||
KeepMessagesDuration newDuration = (KeepMessagesDuration) selection;
|
||||
|
||||
if (newDuration.ordinal() > currentDuration.ordinal()) {
|
||||
new AlertDialog.Builder(activity)
|
||||
.setTitle(R.string.preferences_storage__delete_older_messages)
|
||||
.setMessage(activity.getString(R.string.preferences_storage__this_will_permanently_delete_all_message_history_and_media, activity.getString(newDuration.getStringResource())))
|
||||
.setPositiveButton(R.string.delete, (d, w) -> updateTrimByTime(newDuration))
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
} else {
|
||||
updateTrimByTime(newDuration);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTrimByTime(@NonNull KeepMessagesDuration newDuration) {
|
||||
SignalStore.settings().setKeepMessagesForDuration(newDuration);
|
||||
updateSettingsList();
|
||||
ApplicationDependencies.getTrimThreadsByDateManager().scheduleIfNecessary();
|
||||
}
|
||||
}
|
||||
|
||||
public static class ConversationLengthLimitConfiguration extends BaseSettingsFragment.Configuration implements CustomizableSingleSelectSetting.CustomizableSingleSelectionListener {
|
||||
|
||||
private static final int CUSTOM_LENGTH = -1;
|
||||
|
||||
@Override
|
||||
public void configureAdapter(@NonNull BaseSettingsAdapter adapter) {
|
||||
adapter.configureSingleSelect(this);
|
||||
adapter.configureCustomizableSingleSelect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull MappingModelList getSettings() {
|
||||
int trimLength = SignalStore.settings().isTrimByLengthEnabled() ? SignalStore.settings().getThreadTrimLength() : 0;
|
||||
int[] options = activity.getResources().getIntArray(R.array.conversation_length_limit);
|
||||
boolean hasSelection = false;
|
||||
MappingModelList settings = new MappingModelList();
|
||||
|
||||
for (int option : options) {
|
||||
boolean isSelected = option == trimLength;
|
||||
String text = option == 0 ? activity.getString(R.string.preferences_storage__none)
|
||||
: activity.getString(R.string.preferences_storage__s_messages, NumberFormat.getInstance().format(option));
|
||||
|
||||
settings.add(new SingleSelectSetting.Item(option, text, isSelected));
|
||||
|
||||
hasSelection = hasSelection || isSelected;
|
||||
}
|
||||
|
||||
int value;
|
||||
try {
|
||||
value = Integer.parseInt((String)newValue);
|
||||
} catch (NumberFormatException nfe) {
|
||||
Log.w(TAG, nfe);
|
||||
return false;
|
||||
int currentValue = SignalStore.settings().getThreadTrimLength();
|
||||
settings.add(new CustomizableSingleSelectSetting.Item(CUSTOM_LENGTH,
|
||||
activity.getString(R.string.preferences_storage__custom),
|
||||
!hasSelection,
|
||||
currentValue,
|
||||
activity.getString(R.string.preferences_storage__s_messages, NumberFormat.getInstance().format(currentValue))));
|
||||
return settings;
|
||||
}
|
||||
|
||||
@SuppressLint("InflateParams")
|
||||
@Override
|
||||
public void onCustomizeClicked(@Nullable CustomizableSingleSelectSetting.Item item) {
|
||||
boolean trimLengthEnabled = SignalStore.settings().isTrimByLengthEnabled();
|
||||
int trimLength = trimLengthEnabled ? SignalStore.settings().getThreadTrimLength() : 0;
|
||||
|
||||
View view = LayoutInflater.from(activity).inflate(R.layout.customizable_setting_edit_text, null, false);
|
||||
EditText editText = view.findViewById(R.id.customizable_setting_edit_text);
|
||||
if (trimLength > 0) {
|
||||
editText.setText(String.valueOf(trimLength));
|
||||
}
|
||||
|
||||
if (value < 1) {
|
||||
return false;
|
||||
}
|
||||
AlertDialog dialog = new AlertDialog.Builder(activity)
|
||||
.setTitle(R.string.preferences_Storage__custom_conversation_length_limit)
|
||||
.setView(view)
|
||||
.setPositiveButton(android.R.string.ok, (d, w) -> onSelectionChanged(Integer.parseInt(editText.getText().toString())))
|
||||
.setNegativeButton(android.R.string.cancel, (d, w) -> updateSettingsList())
|
||||
.create();
|
||||
|
||||
preference.setSummary(getResources().getQuantityString(R.plurals.ApplicationPreferencesActivity_messages_per_conversation, value, value));
|
||||
return true;
|
||||
dialog.setOnShowListener(d -> {
|
||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(!TextUtils.isEmpty(editText.getText()));
|
||||
editText.requestFocus();
|
||||
editText.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void afterTextChanged(@NonNull Editable sequence) {
|
||||
CharSequence trimmed = StringUtil.trimSequence(sequence);
|
||||
if (TextUtils.isEmpty(trimmed)) {
|
||||
sequence.replace(0, sequence.length(), "");
|
||||
} else {
|
||||
try {
|
||||
Integer.parseInt(trimmed.toString());
|
||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true);
|
||||
return;
|
||||
} catch (NumberFormatException e) {
|
||||
String onlyDigits = trimmed.toString().replaceAll("[^\\d]", "");
|
||||
if (!onlyDigits.equals(trimmed.toString())) {
|
||||
sequence.replace(0, sequence.length(), onlyDigits);
|
||||
}
|
||||
}
|
||||
}
|
||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(@NonNull CharSequence sequence, int start, int count, int after) {}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(@NonNull CharSequence sequence, int start, int before, int count) {}
|
||||
});
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelectionChanged(@NonNull Object selection) {
|
||||
boolean trimLengthEnabled = SignalStore.settings().isTrimByLengthEnabled();
|
||||
int trimLength = trimLengthEnabled ? SignalStore.settings().getThreadTrimLength() : 0;
|
||||
int newTrimLength = (Integer) selection;
|
||||
|
||||
if (newTrimLength > 0 && (!trimLengthEnabled || newTrimLength < trimLength)) {
|
||||
new AlertDialog.Builder(activity)
|
||||
.setTitle(R.string.preferences_storage__delete_older_messages)
|
||||
.setMessage(activity.getString(R.string.preferences_storage__this_will_permanently_trim_all_conversations_to_the_d_most_recent_messages, NumberFormat.getInstance().format(newTrimLength)))
|
||||
.setPositiveButton(R.string.delete, (d, w) -> updateTrimByLength(newTrimLength))
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
} else if (newTrimLength == CUSTOM_LENGTH) {
|
||||
onCustomizeClicked(null);
|
||||
} else {
|
||||
updateTrimByLength(newTrimLength);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTrimByLength(int length) {
|
||||
boolean restrictingChange = !SignalStore.settings().isTrimByLengthEnabled() || length < SignalStore.settings().getThreadTrimLength();
|
||||
|
||||
SignalStore.settings().setThreadTrimByLengthEnabled(length > 0);
|
||||
SignalStore.settings().setThreadTrimLength(length);
|
||||
updateSettingsList();
|
||||
|
||||
if (SignalStore.settings().isTrimByLengthEnabled() && restrictingChange) {
|
||||
KeepMessagesDuration keepMessagesDuration = SignalStore.settings().getKeepMessagesDuration();
|
||||
|
||||
long trimBeforeDate = keepMessagesDuration != KeepMessagesDuration.FOREVER ? System.currentTimeMillis() - keepMessagesDuration.getDuration()
|
||||
: ThreadDatabase.NO_TRIM_BEFORE_DATE_SET;
|
||||
|
||||
SignalExecutors.BOUNDED.execute(() -> DatabaseFactory.getThreadDatabase(ApplicationDependencies.getApplication()).trimAllThreads(length, trimBeforeDate));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user