clipboard: Enable history collection with a checkbox

The feature is off by default for privacy reasons. The checkbox state is
persisted in the configuration.

The history is immediately cleared when it's disabled. The content of
the system clipboard is visible when the history is enabled.
This commit is contained in:
Jules Aguillon 2024-06-16 22:10:18 +02:00
parent 461f966e6e
commit d5f36885c4
4 changed files with 59 additions and 7 deletions

View File

@ -2,7 +2,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:background="?attr/colorKeyboard" android:hardwareAccelerated="false"> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:background="?attr/colorKeyboard" android:hardwareAccelerated="false">
<ScrollView android:layout_width="fill_parent" android:layout_height="@dimen/clipboard_view_height"> <ScrollView android:layout_width="fill_parent" android:layout_height="@dimen/clipboard_view_height">
<LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content"> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content">
<TextView android:text="@string/clipboard_history_heading" style="@style/clipboardHeading" android:layout_width="fill_parent" android:layout_height="wrap_content"/> <juloo.keyboard2.ClipboardHistoryCheckBox android:text="@string/clipboard_history_heading" style="@style/clipboardHeading" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
<juloo.keyboard2.ClipboardHistoryView android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content" android:divider="?attr/clipboard_divider_color" android:dividerHeight="?attr/clipboard_divider_height"/> <juloo.keyboard2.ClipboardHistoryView android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content" android:divider="?attr/clipboard_divider_color" android:dividerHeight="?attr/clipboard_divider_height"/>
<TextView android:text="@string/clipboard_pin_heading" style="@style/clipboardHeading" android:layout_width="fill_parent" android:layout_height="wrap_content"/> <TextView android:text="@string/clipboard_pin_heading" style="@style/clipboardHeading" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
<juloo.keyboard2.ClipboardPinView android:id="@+id/clipboard_pin_view" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content" android:divider="?attr/clipboard_divider_color" android:dividerHeight="?attr/clipboard_divider_height"/> <juloo.keyboard2.ClipboardPinView android:id="@+id/clipboard_pin_view" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content" android:divider="?attr/clipboard_divider_color" android:dividerHeight="?attr/clipboard_divider_height"/>

View File

@ -0,0 +1,22 @@
package juloo.keyboard2;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.CheckBox;
import android.widget.CompoundButton;
final class ClipboardHistoryCheckBox extends CheckBox
implements CompoundButton.OnCheckedChangeListener
{
public ClipboardHistoryCheckBox(Context ctx, AttributeSet attrs)
{
super(ctx, attrs);
setOnCheckedChangeListener(this);
}
@Override
public void onCheckedChanged(CompoundButton _v, boolean isChecked)
{
ClipboardHistoryService.set_history_enabled(isChecked);
}
}

View File

@ -27,6 +27,19 @@ public final class ClipboardHistoryService
return _service; return _service;
} }
public static void set_history_enabled(boolean e)
{
if (_service == null)
return;
Config.globalPrefs().edit()
.putBoolean("clipboard_history_enabled", e)
.commit();
if (e)
_service.add_current_clip();
else
_service.clear_history();
}
/** The maximum size limits the amount of user data stored in memory but also /** The maximum size limits the amount of user data stored in memory but also
gives a sense to the user that the history is not persisted and can be gives a sense to the user that the history is not persisted and can be
forgotten as soon as the app stops. */ forgotten as soon as the app stops. */
@ -89,6 +102,8 @@ public final class ClipboardHistoryService
empty strings. */ empty strings. */
public void add_clip(String clip) public void add_clip(String clip)
{ {
if (!Config.globalConfig().clipboard_history_enabled)
return;
int size = _history.size(); int size = _history.size();
if (clip.equals("") || (size > 0 && _history.get(size - 1).content.equals(clip))) if (clip.equals("") || (size > 0 && _history.get(size - 1).content.equals(clip)))
return; return;
@ -99,6 +114,13 @@ public final class ClipboardHistoryService
_listener.on_clipboard_history_change(); _listener.on_clipboard_history_change();
} }
public void clear_history()
{
_history.clear();
if (_listener != null)
_listener.on_clipboard_history_change();
}
public void set_on_clipboard_history_change(OnClipboardHistoryChange l) { _listener = l; } public void set_on_clipboard_history_change(OnClipboardHistoryChange l) { _listener = l; }
public static interface OnClipboardHistoryChange public static interface OnClipboardHistoryChange
@ -106,6 +128,17 @@ public final class ClipboardHistoryService
public void on_clipboard_history_change(); public void on_clipboard_history_change();
} }
/** Add what is currently in the system clipboard into the history. */
void add_current_clip()
{
ClipData clip = _cm.getPrimaryClip();
if (clip == null)
return;
int count = clip.getItemCount();
for (int i = 0; i < count; i++)
add_clip(clip.getItemAt(i).getText().toString());
}
final class SystemListener implements ClipboardManager.OnPrimaryClipChangedListener final class SystemListener implements ClipboardManager.OnPrimaryClipChangedListener
{ {
public SystemListener() {} public SystemListener() {}
@ -113,12 +146,7 @@ public final class ClipboardHistoryService
@Override @Override
public void onPrimaryClipChanged() public void onPrimaryClipChanged()
{ {
ClipData clip = _cm.getPrimaryClip(); add_current_clip();
if (clip == null)
return;
int count = clip.getItemCount();
for (int i = 0; i < count; i++)
add_clip(clip.getItemAt(i).getText().toString());
} }
} }

View File

@ -66,6 +66,7 @@ public final class Config
public boolean pin_entry_enabled; public boolean pin_entry_enabled;
public boolean borderConfig; public boolean borderConfig;
public int circle_sensitivity; public int circle_sensitivity;
public boolean clipboard_history_enabled;
// Dynamically set // Dynamically set
public boolean shouldOfferVoiceTyping; public boolean shouldOfferVoiceTyping;
@ -183,6 +184,7 @@ public final class Config
current_layout_portrait = _prefs.getInt("current_layout_portrait", 0); current_layout_portrait = _prefs.getInt("current_layout_portrait", 0);
current_layout_landscape = _prefs.getInt("current_layout_landscape", 0); current_layout_landscape = _prefs.getInt("current_layout_landscape", 0);
circle_sensitivity = Integer.valueOf(_prefs.getString("circle_sensitivity", "2")); circle_sensitivity = Integer.valueOf(_prefs.getString("circle_sensitivity", "2"));
clipboard_history_enabled = _prefs.getBoolean("clipboard_history_enabled", false);
} }
public int get_current_layout() public int get_current_layout()