mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-04-20 06:09:09 +00:00
Added support for disabling clipboard history and clip retention time
This commit is contained in:
parent
1bfb6e2273
commit
ad1672ad5c
14 changed files with 124 additions and 29 deletions
|
@ -67,7 +67,7 @@ class ClipboardAdapter(
|
|||
}
|
||||
|
||||
fun setContent(historyEntry: ClipboardHistoryEntry?) {
|
||||
itemView.tag = historyEntry?.id
|
||||
itemView.tag = historyEntry?.timeStamp
|
||||
contentView.text = historyEntry?.content
|
||||
pinnedIconView.visibility = if (historyEntry?.isPinned == true) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
|
|
@ -136,6 +136,7 @@ class ClipboardHistoryView @JvmOverloads constructor(
|
|||
keyVisualAttr: KeyVisualAttributes?,
|
||||
iconSet: KeyboardIconsSet
|
||||
) {
|
||||
historyManager.prepareClipboardHistory()
|
||||
historyManager.setHistoryChangeListener(this)
|
||||
clipboardHistoryManager = historyManager
|
||||
clipboardAdapter.clipboardHistoryManager = historyManager
|
||||
|
|
|
@ -21,6 +21,7 @@ import android.util.Log;
|
|||
|
||||
import org.dslul.openboard.inputmethod.event.Event;
|
||||
import org.dslul.openboard.inputmethod.latin.common.Constants;
|
||||
import org.dslul.openboard.inputmethod.latin.settings.Settings;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.CapsModeUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.RecapitalizeStatus;
|
||||
|
||||
|
@ -689,7 +690,11 @@ public final class KeyboardState {
|
|||
} else if (code == Constants.CODE_ALPHA_FROM_EMOJI) {
|
||||
setAlphabetKeyboard(autoCapsFlags, recapitalizeMode);
|
||||
} else if (code == Constants.CODE_CLIPBOARD) {
|
||||
setClipboardKeyboard();
|
||||
// Note: Printing clipboard content is handled in
|
||||
// {@link InputLogic#handleFunctionalEvent(Event,InputTransaction,int,LatinIME.UIHandler)}.
|
||||
if (Settings.getInstance().getCurrent().mClipboardHistoryEnabled) {
|
||||
setClipboardKeyboard();
|
||||
}
|
||||
} else if (code == Constants.CODE_ALPHA_FROM_CLIPBOARD) {
|
||||
setAlphabetKeyboard(autoCapsFlags, recapitalizeMode);
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package org.dslul.openboard.inputmethod.latin
|
||||
|
||||
data class ClipboardHistoryEntry (
|
||||
var id: Long,
|
||||
var timeStamp: Long,
|
||||
val content: CharSequence,
|
||||
var isPinned: Boolean = false
|
||||
) : Comparable<ClipboardHistoryEntry> {
|
||||
|
||||
override fun compareTo(other: ClipboardHistoryEntry): Int {
|
||||
val result = other.isPinned.compareTo(isPinned)
|
||||
return if (result != 0) result else other.id.compareTo(id)
|
||||
return if (result != 0) result else other.timeStamp.compareTo(timeStamp)
|
||||
}
|
||||
}
|
|
@ -2,11 +2,9 @@ package org.dslul.openboard.inputmethod.latin
|
|||
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.text.TextUtils
|
||||
import android.util.Base64
|
||||
import android.util.Log
|
||||
import androidx.annotation.RequiresApi
|
||||
import org.dslul.openboard.inputmethod.compat.ClipboardManagerCompat
|
||||
import org.dslul.openboard.inputmethod.latin.utils.JsonUtils
|
||||
import java.io.File
|
||||
|
@ -44,7 +42,12 @@ class ClipboardHistoryManager(
|
|||
clipboardManager.removePrimaryClipChangedListener(this)
|
||||
}
|
||||
|
||||
override fun onPrimaryClipChanged() = fetchPrimaryClip()
|
||||
override fun onPrimaryClipChanged() {
|
||||
// Make sure we read clipboard content only if history settings is set
|
||||
if (latinIME.mSettings.current?.mClipboardHistoryEnabled == true) {
|
||||
fetchPrimaryClip()
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchPrimaryClip() {
|
||||
val clipData = clipboardManager.primaryClip ?: return
|
||||
|
@ -53,14 +56,14 @@ class ClipboardHistoryManager(
|
|||
// Starting from API 30, onPrimaryClipChanged() can be called multiple times
|
||||
// for the same clip. We can identify clips with their timestamps since API 26.
|
||||
// We use that to prevent unwanted duplicates.
|
||||
val id = ClipboardManagerCompat.getClipTimestamp(clipData)?.also { stamp ->
|
||||
if (historyEntries.any { it.id == stamp }) return
|
||||
val timeStamp = ClipboardManagerCompat.getClipTimestamp(clipData)?.also { stamp ->
|
||||
if (historyEntries.any { it.timeStamp == stamp }) return
|
||||
} ?: System.currentTimeMillis()
|
||||
|
||||
val content = clipItem.coerceToText(latinIME)
|
||||
if (TextUtils.isEmpty(content)) return
|
||||
|
||||
val entry = ClipboardHistoryEntry(id, content)
|
||||
val entry = ClipboardHistoryEntry(timeStamp, content)
|
||||
historyEntries.add(entry)
|
||||
sortHistoryEntries()
|
||||
val at = historyEntries.indexOf(entry)
|
||||
|
@ -68,10 +71,10 @@ class ClipboardHistoryManager(
|
|||
}
|
||||
}
|
||||
|
||||
fun toggleClipPinned(clipId: Long) {
|
||||
val from = historyEntries.indexOfFirst { it.id == clipId }
|
||||
fun toggleClipPinned(ts: Long) {
|
||||
val from = historyEntries.indexOfFirst { it.timeStamp == ts }
|
||||
val historyEntry = historyEntries[from].apply {
|
||||
id = System.currentTimeMillis()
|
||||
timeStamp = System.currentTimeMillis()
|
||||
isPinned = !isPinned
|
||||
}
|
||||
sortHistoryEntries()
|
||||
|
@ -94,16 +97,34 @@ class ClipboardHistoryManager(
|
|||
historyEntries.sort()
|
||||
}
|
||||
|
||||
private fun checkClipRetentionElapsed() {
|
||||
val mins = latinIME.mSettings.current.mClipboardHistoryRetentionTime
|
||||
if (mins <= 0) return // No retention limit
|
||||
val maxClipRetentionTime = mins * 60 * 1000L
|
||||
val now = System.currentTimeMillis()
|
||||
historyEntries.removeAll { !it.isPinned && (now - it.timeStamp) > maxClipRetentionTime }
|
||||
}
|
||||
|
||||
// We do not want to update history while user is visualizing it, so we check retention only
|
||||
// when history is about to be shown
|
||||
fun prepareClipboardHistory() = checkClipRetentionElapsed()
|
||||
|
||||
fun getHistorySize() = historyEntries.size
|
||||
|
||||
fun getHistoryEntry(position: Int) = historyEntries[position]
|
||||
|
||||
fun getHistoryEntryContent(id: Long) = historyEntries.first { it.id == id }
|
||||
fun getHistoryEntryContent(timeStamp: Long) = historyEntries.first { it.timeStamp == timeStamp }
|
||||
|
||||
fun setHistoryChangeListener(l: OnHistoryChangeListener?) {
|
||||
onHistoryChangeListener = l
|
||||
}
|
||||
|
||||
fun retrieveClipboardContent(): CharSequence {
|
||||
val clipData = clipboardManager.primaryClip ?: return ""
|
||||
if (clipData.itemCount == 0) return ""
|
||||
return clipData.getItemAt(0)?.coerceToText(latinIME) ?: ""
|
||||
}
|
||||
|
||||
private fun startLoadPinnedClipsFromDisk() {
|
||||
object : Thread("$TAG-load") {
|
||||
override fun run() {
|
||||
|
|
|
@ -693,8 +693,17 @@ public final class InputLogic {
|
|||
// handled in {@link KeyboardState#onEvent(Event,int)}.
|
||||
break;
|
||||
case Constants.CODE_CLIPBOARD:
|
||||
// Note: Switching clipboard keyboard is being handled in
|
||||
// {@link KeyboardState#onEvent(Event,int)}.
|
||||
// Note: If clipboard history is enabled, switching to clipboard keyboard
|
||||
// is being handled in {@link KeyboardState#onEvent(Event,int)}.
|
||||
// If disabled, current clipboard content is committed.
|
||||
if (!inputTransaction.getMSettingsValues().mClipboardHistoryEnabled) {
|
||||
final CharSequence content = mLatinIME.getClipboardHistoryManager()
|
||||
.retrieveClipboardContent();
|
||||
if (!TextUtils.isEmpty(content)) {
|
||||
mConnection.commitText(content, 1);
|
||||
inputTransaction.setDidAffectContents();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Constants.CODE_ALPHA_FROM_CLIPBOARD:
|
||||
// Note: Switching back from clipboard keyboard to the main keyboard is being
|
||||
|
|
|
@ -60,9 +60,8 @@ public final class PreferencesSettingsFragment extends SubScreenFragment {
|
|||
|
||||
setupKeypressVibrationDurationSettings();
|
||||
setupKeypressSoundVolumeSettings();
|
||||
setupKeyLongpressTimeoutSettings();
|
||||
refreshEnablingsOfKeypressSoundAndVibrationSettings();
|
||||
refreshEnablingsOfKeypressSoundAndVibrationSettings();
|
||||
setupHistoryRetentionTimeSettings();
|
||||
refreshEnablingsOfKeypressSoundAndVibrationAndHistRetentionSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -79,16 +78,18 @@ public final class PreferencesSettingsFragment extends SubScreenFragment {
|
|||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
|
||||
refreshEnablingsOfKeypressSoundAndVibrationSettings();
|
||||
refreshEnablingsOfKeypressSoundAndVibrationAndHistRetentionSettings();
|
||||
}
|
||||
|
||||
private void refreshEnablingsOfKeypressSoundAndVibrationSettings() {
|
||||
private void refreshEnablingsOfKeypressSoundAndVibrationAndHistRetentionSettings() {
|
||||
final SharedPreferences prefs = getSharedPreferences();
|
||||
final Resources res = getResources();
|
||||
setPreferenceEnabled(Settings.PREF_VIBRATION_DURATION_SETTINGS,
|
||||
Settings.readVibrationEnabled(prefs, res));
|
||||
setPreferenceEnabled(Settings.PREF_KEYPRESS_SOUND_VOLUME,
|
||||
Settings.readKeypressSoundEnabled(prefs, res));
|
||||
setPreferenceEnabled(Settings.PREF_CLIPBOARD_HISTORY_RETENTION_TIME,
|
||||
Settings.readClipboardHistoryEnabled(prefs));
|
||||
}
|
||||
|
||||
private void setupKeypressVibrationDurationSettings() {
|
||||
|
@ -191,11 +192,11 @@ public final class PreferencesSettingsFragment extends SubScreenFragment {
|
|||
});
|
||||
}
|
||||
|
||||
private void setupKeyLongpressTimeoutSettings() {
|
||||
private void setupHistoryRetentionTimeSettings() {
|
||||
final SharedPreferences prefs = getSharedPreferences();
|
||||
final Resources res = getResources();
|
||||
final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference(
|
||||
Settings.PREF_KEY_LONGPRESS_TIMEOUT);
|
||||
Settings.PREF_CLIPBOARD_HISTORY_RETENTION_TIME);
|
||||
if (pref == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -212,17 +213,20 @@ public final class PreferencesSettingsFragment extends SubScreenFragment {
|
|||
|
||||
@Override
|
||||
public int readValue(final String key) {
|
||||
return Settings.readKeyLongpressTimeout(prefs, res);
|
||||
return Settings.readClipboardHistoryRetentionTime(prefs, res);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readDefaultValue(final String key) {
|
||||
return Settings.readDefaultKeyLongpressTimeout(res);
|
||||
return Settings.readDefaultClipboardHistoryRetentionTime(res);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueText(final int value) {
|
||||
return res.getString(R.string.abbreviation_unit_milliseconds, value);
|
||||
if (value <= 0) {
|
||||
return res.getString(R.string.settings_no_limit);
|
||||
}
|
||||
return res.getString(R.string.abbreviation_unit_minutes, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -118,6 +118,9 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
|||
|
||||
public static final String PREF_SPACE_TO_CHANGE_LANG = "prefs_long_press_keyboard_to_change_lang";
|
||||
|
||||
public static final String PREF_ENABLE_CLIPBOARD_HISTORY = "pref_enable_clipboard_history";
|
||||
public static final String PREF_CLIPBOARD_HISTORY_RETENTION_TIME = "pref_clipboard_history_retention_time";
|
||||
|
||||
// This preference key is deprecated. Use {@link #PREF_SHOW_LANGUAGE_SWITCH_KEY} instead.
|
||||
// This is being used only for the backward compatibility.
|
||||
private static final String PREF_SUPPRESS_LANGUAGE_SWITCH_KEY =
|
||||
|
@ -348,6 +351,22 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
|||
final int milliseconds = prefs.getInt(prefKey, UNDEFINED_PREFERENCE_VALUE_INT);
|
||||
return (milliseconds != UNDEFINED_PREFERENCE_VALUE_INT) ? milliseconds : defaultValue;
|
||||
}
|
||||
|
||||
public static boolean readClipboardHistoryEnabled(final SharedPreferences prefs) {
|
||||
return prefs.getBoolean(PREF_ENABLE_CLIPBOARD_HISTORY, true);
|
||||
}
|
||||
|
||||
public static int readClipboardHistoryRetentionTime(final SharedPreferences prefs,
|
||||
final Resources res) {
|
||||
final int minutes = prefs.getInt(
|
||||
PREF_CLIPBOARD_HISTORY_RETENTION_TIME, UNDEFINED_PREFERENCE_VALUE_INT);
|
||||
return (minutes != UNDEFINED_PREFERENCE_VALUE_INT) ? minutes
|
||||
: readDefaultClipboardHistoryRetentionTime(res);
|
||||
}
|
||||
|
||||
public static int readDefaultClipboardHistoryRetentionTime(final Resources res) {
|
||||
return res.getInteger(R.integer.config_clipboard_history_retention_time);
|
||||
}
|
||||
|
||||
public static boolean readShowsNumberRow(final SharedPreferences prefs) {
|
||||
return prefs.getBoolean(PREF_SHOW_NUMBER_ROW, false);
|
||||
|
|
|
@ -80,6 +80,8 @@ public class SettingsValues {
|
|||
public final boolean mBlockPotentiallyOffensive;
|
||||
public final boolean mSpaceTrackpadEnabled;
|
||||
public final boolean mDeleteSwipeEnabled;
|
||||
public final boolean mClipboardHistoryEnabled;
|
||||
public final long mClipboardHistoryRetentionTime;
|
||||
// Use bigrams to predict the next word when there is no input for it yet
|
||||
public final boolean mBigramPredictionEnabled;
|
||||
public final boolean mGestureInputEnabled;
|
||||
|
@ -233,6 +235,8 @@ public class SettingsValues {
|
|||
}
|
||||
mSpaceTrackpadEnabled = Settings.readSpaceTrackpadEnabled(prefs);
|
||||
mDeleteSwipeEnabled = Settings.readDeleteSwipeEnabled(prefs);
|
||||
mClipboardHistoryEnabled = Settings.readClipboardHistoryEnabled(prefs);
|
||||
mClipboardHistoryRetentionTime = Settings.readClipboardHistoryRetentionTime(prefs, res);
|
||||
}
|
||||
|
||||
public boolean isMetricsLoggingEnabled() {
|
||||
|
|
|
@ -443,8 +443,9 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
|||
return;
|
||||
}
|
||||
if (view == mClipboardKey) {
|
||||
final KeyboardSwitcher switcher = KeyboardSwitcher.getInstance();
|
||||
switcher.onToggleKeyboard(KeyboardSwitcher.KeyboardSwitchState.CLIPBOARD);
|
||||
mListener.onCodeInput(Constants.CODE_CLIPBOARD,
|
||||
Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE,
|
||||
false /* isKeyRepeat */);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -142,7 +142,7 @@ public final class JsonUtils {
|
|||
writer.beginArray();
|
||||
for (final ClipboardHistoryEntry e : entries) {
|
||||
writer.beginObject();
|
||||
writer.name(CLIPBOARD_HISTORY_ENTRY_ID_KEY).value(e.getId());
|
||||
writer.name(CLIPBOARD_HISTORY_ENTRY_ID_KEY).value(e.getTimeStamp());
|
||||
writer.name(CLIPBOARD_HISTORY_ENTRY_CONTENT_KEY).value(e.getContent().toString());
|
||||
writer.endObject();
|
||||
}
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
<resources>
|
||||
<bool name="config_use_fullscreen_mode">false</bool>
|
||||
|
||||
<!-- Maximum time for a clipboard history entry to be kept, in minutes. -->
|
||||
<integer name="config_clipboard_history_retention_time">10</integer>
|
||||
|
||||
<dimen name="config_key_hysteresis_distance">8.0dp</dimen>
|
||||
|
||||
<!-- Preferable keyboard height in absolute scale: 1.285in -->
|
||||
|
|
|
@ -57,6 +57,8 @@
|
|||
<string name="settings_category_input">Input</string>
|
||||
<!-- Settings category title for Preference/Additional keys settings [CHAR LIMIT=33] -->
|
||||
<string name="settings_category_additional_keys">Additional keys</string>
|
||||
<!-- Settings category title for Preference/Additional keys settings [CHAR LIMIT=33] -->
|
||||
<string name="settings_category_clipboard_history">Clipboard history</string>
|
||||
<!-- Settings category title for Text correction/Corrections [CHAR LIMIT=33] -->
|
||||
<string name="settings_category_correction">Corrections</string>
|
||||
<!-- Settings category title for Text correction/Suggestions [CHAR LIMIT=33] -->
|
||||
|
@ -97,8 +99,12 @@
|
|||
<string name="key_preview_popup_dismiss_default_delay">Default</string>
|
||||
<!-- Units abbreviation for the duration (milliseconds) [CHAR LIMIT=10] -->
|
||||
<string name="abbreviation_unit_milliseconds"><xliff:g id="MILLISECONDS">%s</xliff:g>ms</string>
|
||||
<!-- Units abbreviation for the duration (milliseconds) [CHAR LIMIT=10] -->
|
||||
<string name="abbreviation_unit_minutes"><xliff:g id="MILLISECONDS">%s</xliff:g>min.</string>
|
||||
<!-- The text that represents the current settings value is the system default [CHAR LIMIT=25] -->
|
||||
<string name="settings_system_default">System default</string>
|
||||
<!-- The text that represents an unlimited delay [CHAR LIMIT=25] -->
|
||||
<string name="settings_no_limit">No limit</string>
|
||||
<!-- Option name for enabling or disabling the use of names of people in Contacts for suggestion and correction [CHAR LIMIT=25] -->
|
||||
<string name="use_contacts_dict">Suggest Contact names</string>
|
||||
<!-- Description for option enabling or disabling the use of names of people in Contacts for suggestion and correction [CHAR LIMIT=65] -->
|
||||
|
@ -166,6 +172,12 @@
|
|||
<string name="voice_input_disabled_summary">No voice input methods enabled. Check Languages & input settings.</string>
|
||||
<!-- Preferences item for enabling clipboard key -->
|
||||
<string name="show_clipboard_key">Clipboard key</string>
|
||||
<!-- Preferences item for enabling clipboard history -->
|
||||
<string name="enable_clipboard_history">Enable clipboard history</string>
|
||||
<!-- Description for enabling/disabling clipboard history mentioning that if disabled, clipboard content is pasted -->
|
||||
<string name="enable_clipboard_history_summary">If disabled, clipboard key will paste clipboard content if any</string>
|
||||
<!-- Preferences item for enabling clipboard history -->
|
||||
<string name="clipboard_history_retention_time">History retention time</string>
|
||||
<!-- Preferences item for enabling swipe deletion -->
|
||||
<string name="delete_swipe">Delete swipe</string>
|
||||
<!-- Description for "delete_swipe" option. -->
|
||||
|
|
|
@ -93,4 +93,20 @@
|
|||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:title="@string/settings_category_clipboard_history">
|
||||
|
||||
<CheckBoxPreference
|
||||
android:key="pref_enable_clipboard_history"
|
||||
android:title="@string/enable_clipboard_history"
|
||||
android:summary="@string/enable_clipboard_history_summary"
|
||||
android:defaultValue="true"
|
||||
android:persistent="true" />
|
||||
|
||||
<org.dslul.openboard.inputmethod.latin.settings.SeekBarDialogPreference
|
||||
android:key="pref_clipboard_history_retention_time"
|
||||
android:title="@string/clipboard_history_retention_time"
|
||||
latin:maxValue="120" /> <!-- minutes -->
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
||||
|
|
Loading…
Add table
Reference in a new issue