forked from extern/Unexpected-Keyboard
clipboard: Pinning
Allow recent clips to be pinned. Pinned clips are put a different place and are persistent. The pane is split in two columns, the clipboard history and the pinned clips. Pinned clips are stored in a new preference file. Improved pinning layout clipboard: Remove history entry after pinning
This commit is contained in:
parent
58cb6ca232
commit
3d95af5806
5
res/layout/clipboard_history_entry.xml
Normal file
5
res/layout/clipboard_history_entry.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content">
|
||||
<TextView android:id="@+id/clipboard_entry_text" style="@style/clipboardEntry"/>
|
||||
<View android:id="@+id/clipboard_entry_addpin" style="@style/clipboardEntryButton" android:background="@android:drawable/ic_menu_add"/>
|
||||
</LinearLayout>
|
@ -1,6 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:background="?attr/colorKeyboard" android:hardwareAccelerated="false">
|
||||
<LinearLayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="@dimen/clipboard_view_height">
|
||||
<LinearLayout android:orientation="vertical" android:layout_weight="1" android:layout_width="fill_parent" android:layout_height="fill_parent">
|
||||
<TextView android:text="@string/clipboard_history_heading" style="@style/clipboardHeading" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
|
||||
<juloo.keyboard2.ClipboardHistoryView android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="@dimen/clipboard_view_height" android:divider="?attr/clipboard_divider_color" android:dividerHeight="?attr/clipboard_divider_height"/>
|
||||
<juloo.keyboard2.ClipboardHistoryView android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" android:divider="?attr/clipboard_divider_color" android:dividerHeight="?attr/clipboard_divider_height"/>
|
||||
</LinearLayout>
|
||||
<LinearLayout android:orientation="vertical" android:layout_weight="1" android:layout_width="fill_parent" android:layout_height="fill_parent">
|
||||
<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="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" android:divider="?attr/clipboard_divider_color" android:dividerHeight="?attr/clipboard_divider_height"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
<juloo.keyboard2.Keyboard2View layout="@xml/clipboard_bottom_row" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="?attr/colorKeyboard"/>
|
||||
</LinearLayout>
|
||||
|
@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content">
|
||||
<TextView android:id="@android:id/text1" style="@style/clipboardEntry" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
|
||||
</LinearLayout>
|
5
res/layout/clipboard_pin_entry.xml
Normal file
5
res/layout/clipboard_pin_entry.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content">
|
||||
<TextView android:id="@+id/clipboard_pin_text" style="@style/clipboardEntry" android:maxLines="3"/>
|
||||
<View android:id="@+id/clipboard_pin_remove" style="@style/clipboardEntryButton" android:background="@android:drawable/ic_menu_delete"/>
|
||||
</LinearLayout>
|
@ -116,4 +116,5 @@ Tato aplikace neobsahuje žádné reklamy, nevyužívá připojení k síti a je
|
||||
<string name="key_descr_home">Home</string>
|
||||
<string name="key_descr_end">End</string>
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
<!-- <string name="clipboard_pin_heading">Pinned</string> -->
|
||||
</resources>
|
||||
|
@ -116,4 +116,5 @@ Diese App enthält keine Werbung, benötigt keinen Netzwerkzugriff und ist quell
|
||||
<string name="key_descr_home">Pos1</string>
|
||||
<string name="key_descr_end">Ende</string>
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
<!-- <string name="clipboard_pin_heading">Pinned</string> -->
|
||||
</resources>
|
||||
|
@ -116,4 +116,5 @@ La misma no contiene ningún anuncio/publicidad, no realiza peticiones de red y
|
||||
<string name="key_descr_home">Inicio</string>
|
||||
<string name="key_descr_end">Fin</string>
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
<!-- <string name="clipboard_pin_heading">Pinned</string> -->
|
||||
</resources>
|
||||
|
@ -116,4 +116,5 @@ This application contains no ads, doesn't make any network requests and is Open
|
||||
<!-- <string name="key_descr_home">Home</string> -->
|
||||
<!-- <string name="key_descr_end">End</string> -->
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
<!-- <string name="clipboard_pin_heading">Pinned</string> -->
|
||||
</resources>
|
||||
|
@ -116,4 +116,5 @@ Cette application ne contient pas de publicité, n'accède pas au réseau et est
|
||||
<string name="key_descr_home">Début</string>
|
||||
<string name="key_descr_end">Fin</string>
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
<!-- <string name="clipboard_pin_heading">Pinned</string> -->
|
||||
</resources>
|
||||
|
@ -116,4 +116,5 @@ This application contains no ads, doesn't make any network requests and is Open
|
||||
<!-- <string name="key_descr_home">Home</string> -->
|
||||
<!-- <string name="key_descr_end">End</string> -->
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
<!-- <string name="clipboard_pin_heading">Pinned</string> -->
|
||||
</resources>
|
||||
|
@ -116,4 +116,5 @@ This application contains no ads, doesn't make any network requests and is Open
|
||||
<!-- <string name="key_descr_home">Home</string> -->
|
||||
<!-- <string name="key_descr_end">End</string> -->
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
<!-- <string name="clipboard_pin_heading">Pinned</string> -->
|
||||
</resources>
|
||||
|
@ -118,4 +118,5 @@ Tagad lieliski piemērota izmantošanai ikdienā.
|
||||
<string name="key_descr_home">Sākums</string>
|
||||
<string name="key_descr_end">Beigas</string>
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
<!-- <string name="clipboard_pin_heading">Pinned</string> -->
|
||||
</resources>
|
||||
|
@ -116,4 +116,5 @@ Aplikacja nie zawiera reklam, nie żąda dostępu do internetu, a jej kod źród
|
||||
<string name="key_descr_home">Home</string>
|
||||
<string name="key_descr_end">End</string>
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
<!-- <string name="clipboard_pin_heading">Pinned</string> -->
|
||||
</resources>
|
||||
|
@ -116,4 +116,5 @@ Este aplicativo não contém anúncios, não faz nenhuma solicitação de rede e
|
||||
<string name="key_descr_home">Home</string>
|
||||
<string name="key_descr_end">End</string>
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
<!-- <string name="clipboard_pin_heading">Pinned</string> -->
|
||||
</resources>
|
||||
|
@ -116,4 +116,5 @@ Această aplicație nu conține publicitate, nu folosește rețeaua deloc și e
|
||||
<!-- <string name="key_descr_home">Home</string> -->
|
||||
<!-- <string name="key_descr_end">End</string> -->
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
<!-- <string name="clipboard_pin_heading">Pinned</string> -->
|
||||
</resources>
|
||||
|
@ -116,4 +116,5 @@
|
||||
<string name="key_descr_home">Home</string>
|
||||
<string name="key_descr_end">End</string>
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
<!-- <string name="clipboard_pin_heading">Pinned</string> -->
|
||||
</resources>
|
||||
|
@ -116,4 +116,5 @@ Bu uygulama açık kaynaklıdır. Reklam içermez ve internete bağlanmaz."</str
|
||||
<string name="key_descr_home">BAŞ(Sol yön tuşu)</string>
|
||||
<string name="key_descr_end">SON(Sağ yön tuşu)</string>
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
<!-- <string name="clipboard_pin_heading">Pinned</string> -->
|
||||
</resources>
|
||||
|
@ -116,4 +116,5 @@
|
||||
<string name="key_descr_home">Home</string>
|
||||
<string name="key_descr_end">End</string>
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
<!-- <string name="clipboard_pin_heading">Pinned</string> -->
|
||||
</resources>
|
||||
|
@ -116,4 +116,5 @@ Bây giờ đã hoàn hảo cho việc sử dụng hàng ngày.
|
||||
<!-- <string name="key_descr_home">Home</string> -->
|
||||
<!-- <string name="key_descr_end">End</string> -->
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
<!-- <string name="clipboard_pin_heading">Pinned</string> -->
|
||||
</resources>
|
||||
|
@ -116,4 +116,5 @@
|
||||
<string name="key_descr_home">Home</string>
|
||||
<string name="key_descr_end">End</string>
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
<!-- <string name="clipboard_pin_heading">Pinned</string> -->
|
||||
</resources>
|
||||
|
@ -116,4 +116,5 @@ This application contains no ads, doesn't make any network requests and is Open
|
||||
<string name="key_descr_home">Home</string>
|
||||
<string name="key_descr_end">End</string>
|
||||
<string name="clipboard_history_heading">Recently copied text</string>
|
||||
<string name="clipboard_pin_heading">Pinned</string>
|
||||
</resources>
|
||||
|
@ -18,6 +18,9 @@
|
||||
</style>
|
||||
<!-- Clipboard pane -->
|
||||
<style name="clipboardEntry">
|
||||
<item name="android:layout_weight">1</item>
|
||||
<item name="android:layout_width">fill_parent</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:layout_marginHorizontal">14dp</item>
|
||||
<item name="android:layout_marginVertical">14dp</item>
|
||||
<item name="android:textSize">16dp</item>
|
||||
@ -31,6 +34,13 @@
|
||||
<item name="android:fontWeight">700</item>
|
||||
<item name="android:textColor">?attr/colorSubLabel</item>
|
||||
</style>
|
||||
<style name="clipboardEntryButton">
|
||||
<item name="android:layout_gravity">top</item>
|
||||
<item name="android:layout_width">24dp</item>
|
||||
<item name="android:layout_height">24dp</item>
|
||||
<item name="android:layout_marginVertical">14dp</item>
|
||||
<item name="android:layout_marginRight">6dp</item>
|
||||
</style>
|
||||
<!-- Launcher activity -->
|
||||
<style name="paragraph">
|
||||
<item name="android:layout_width">fill_parent</item>
|
||||
|
@ -46,6 +46,28 @@ public final class ClipboardHistoryService
|
||||
|
||||
public List<String> get_history() { return _history; }
|
||||
|
||||
/** This will call [on_clipboard_history_change]. */
|
||||
public void remove_history_entry(String clip)
|
||||
{
|
||||
int last_pos = _history.size() - 1;
|
||||
for (int pos = last_pos; pos >= 0; pos--)
|
||||
{
|
||||
if (!_history.get(pos).equals(clip))
|
||||
continue;
|
||||
// Removing the current clipboard, clear the system clipboard.
|
||||
if (pos == last_pos)
|
||||
{
|
||||
if (VERSION.SDK_INT >= 28)
|
||||
_cm.clearPrimaryClip();
|
||||
else
|
||||
_cm.setText("");
|
||||
}
|
||||
_history.remove(pos);
|
||||
if (_listener != null)
|
||||
_listener.on_clipboard_history_change(_history);
|
||||
}
|
||||
}
|
||||
|
||||
/** Add clipboard entries to the history, skipping consecutive duplicates and
|
||||
empty strings. */
|
||||
public void add_clip(String clip)
|
||||
|
@ -15,6 +15,7 @@ public final class ClipboardHistoryView extends ListView
|
||||
implements ClipboardHistoryService.OnClipboardHistoryChange
|
||||
{
|
||||
List<String> _history;
|
||||
ClipboardHistoryService _service;
|
||||
ClipboardEntriesAdapter _adapter;
|
||||
|
||||
public ClipboardHistoryView(Context ctx, AttributeSet attrs)
|
||||
@ -22,15 +23,25 @@ public final class ClipboardHistoryView extends ListView
|
||||
super(ctx, attrs);
|
||||
_history = Collections.EMPTY_LIST;
|
||||
_adapter = this.new ClipboardEntriesAdapter();
|
||||
ClipboardHistoryService service = ClipboardHistoryService.get_service(ctx);
|
||||
if (service != null)
|
||||
_service = ClipboardHistoryService.get_service(ctx);
|
||||
if (_service != null)
|
||||
{
|
||||
service.set_on_clipboard_history_change(this);
|
||||
_history = service.get_history();
|
||||
_service.set_on_clipboard_history_change(this);
|
||||
_history = _service.get_history();
|
||||
}
|
||||
setAdapter(_adapter);
|
||||
}
|
||||
|
||||
/** The history entry at index [pos] is removed from the history and added to
|
||||
the list of pinned clipboards. */
|
||||
public void pin_entry(int pos)
|
||||
{
|
||||
ClipboardPinView v = (ClipboardPinView)((ViewGroup)getParent().getParent()).findViewById(R.id.clipboard_pin_view);
|
||||
String clip = _history.get(pos);
|
||||
v.add_entry(clip);
|
||||
_service.remove_history_entry(clip);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void on_clipboard_history_change(List<String> history)
|
||||
{
|
||||
@ -51,27 +62,25 @@ public final class ClipboardHistoryView extends ListView
|
||||
public ClipboardEntriesAdapter() {}
|
||||
|
||||
@Override
|
||||
public int getCount()
|
||||
{
|
||||
return _history.size();
|
||||
}
|
||||
|
||||
public Object getItem(int pos)
|
||||
{
|
||||
return _history.get(pos);
|
||||
}
|
||||
|
||||
public long getItemId(int pos)
|
||||
{
|
||||
return _history.get(pos).hashCode();
|
||||
}
|
||||
public int getCount() { return _history.size(); }
|
||||
@Override
|
||||
public Object getItem(int pos) { return _history.get(pos); }
|
||||
@Override
|
||||
public long getItemId(int pos) { return _history.get(pos).hashCode(); }
|
||||
|
||||
@Override
|
||||
public View getView(int pos, View v, ViewGroup _parent)
|
||||
public View getView(final int pos, View v, ViewGroup _parent)
|
||||
{
|
||||
if (v == null)
|
||||
v = View.inflate(getContext(), R.layout.clipboard_pane_entry, null);
|
||||
((TextView)v.findViewById(android.R.id.text1)).setText(_history.get(pos));
|
||||
v = View.inflate(getContext(), R.layout.clipboard_history_entry, null);
|
||||
((TextView)v.findViewById(R.id.clipboard_entry_text))
|
||||
.setText(_history.get(pos));
|
||||
v.findViewById(R.id.clipboard_entry_addpin).setOnClickListener(
|
||||
new View.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View v) { pin_entry(pos); }
|
||||
});
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
112
srcs/juloo.keyboard2/ClipboardPinView.java
Normal file
112
srcs/juloo.keyboard2/ClipboardPinView.java
Normal file
@ -0,0 +1,112 @@
|
||||
package juloo.keyboard2;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
public final class ClipboardPinView extends ListView
|
||||
{
|
||||
/** Preference file name that store pinned clipboards. */
|
||||
static final String PERSIST_FILE_NAME = "clipboards";
|
||||
/** Preference name for pinned clipboards. */
|
||||
static final String PERSIST_PREF = "pinned";
|
||||
|
||||
List<String> _entries;
|
||||
ClipboardPinEntriesAdapter _adapter;
|
||||
SharedPreferences _persist_store;
|
||||
|
||||
public ClipboardPinView(Context ctx, AttributeSet attrs)
|
||||
{
|
||||
super(ctx, attrs);
|
||||
_entries = new ArrayList<String>();
|
||||
_persist_store =
|
||||
ctx.getSharedPreferences("pinned_clipboards", Context.MODE_PRIVATE);
|
||||
load_from_prefs(_persist_store, _entries);
|
||||
_adapter = this.new ClipboardPinEntriesAdapter();
|
||||
setAdapter(_adapter);
|
||||
}
|
||||
|
||||
/** Pin a clipboard and persist the change. */
|
||||
public void add_entry(String text)
|
||||
{
|
||||
_entries.add(text);
|
||||
_adapter.notifyDataSetChanged();
|
||||
persist();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
/** Remove the entry at index [pos] and persist the change. */
|
||||
public void remove_entry(int pos)
|
||||
{
|
||||
if (pos < 0 || pos >= _entries.size())
|
||||
return;
|
||||
_entries.remove(pos);
|
||||
_adapter.notifyDataSetChanged();
|
||||
persist();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void persist() { save_to_prefs(_persist_store, _entries); }
|
||||
|
||||
static void load_from_prefs(SharedPreferences store, List<String> dst)
|
||||
{
|
||||
String arr_s = store.getString(PERSIST_PREF, null);
|
||||
if (arr_s == null)
|
||||
return;
|
||||
try
|
||||
{
|
||||
JSONArray arr = new JSONArray(arr_s);
|
||||
for (int i = 0; i < arr.length(); i++)
|
||||
dst.add(arr.getString(i));
|
||||
}
|
||||
catch (JSONException _e) {}
|
||||
}
|
||||
|
||||
static void save_to_prefs(SharedPreferences store, List<String> entries)
|
||||
{
|
||||
JSONArray arr = new JSONArray();
|
||||
for (int i = 0; i < entries.size(); i++)
|
||||
arr.put(entries.get(i));
|
||||
store.edit()
|
||||
.putString(PERSIST_PREF, arr.toString())
|
||||
.commit();
|
||||
}
|
||||
|
||||
class ClipboardPinEntriesAdapter extends BaseAdapter
|
||||
{
|
||||
public ClipboardPinEntriesAdapter() {}
|
||||
|
||||
@Override
|
||||
public int getCount() { return _entries.size(); }
|
||||
@Override
|
||||
public Object getItem(int pos) { return _entries.get(pos); }
|
||||
@Override
|
||||
public long getItemId(int pos) { return _entries.get(pos).hashCode(); }
|
||||
|
||||
@Override
|
||||
public View getView(final int pos, View v, ViewGroup _parent)
|
||||
{
|
||||
if (v == null)
|
||||
v = View.inflate(getContext(), R.layout.clipboard_pin_entry, null);
|
||||
((TextView)v.findViewById(R.id.clipboard_pin_text))
|
||||
.setText(_entries.get(pos));
|
||||
v.findViewById(R.id.clipboard_pin_remove).setOnClickListener(
|
||||
new View.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View v) { remove_entry(pos); }
|
||||
});
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user