forked from extern/Unexpected-Keyboard
Clipboard history pane
Work in progress: It's not yet possible to paste from the pane. The pane can be switched to and from and displays the strings recently added to the clipboard. ClipboardHistoryService listens for change to the system clipboard and keep the history in memory. This data is not persisted to the storage. 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 forgotten as soon as the app stops.
This commit is contained in:
parent
45fc18576e
commit
58cb6ca232
@ -6,7 +6,8 @@ warning_count = 0
|
||||
KNOWN_NOT_LAYOUT = set([
|
||||
"number_row", "numpad", "pin",
|
||||
"bottom_row", "settings", "method",
|
||||
"greekmath", "numeric", "emoji_bottom_row" ])
|
||||
"greekmath", "numeric", "emoji_bottom_row",
|
||||
"clipboard_bottom_row" ])
|
||||
|
||||
def warn(msg):
|
||||
global warning_count
|
||||
|
6
res/layout/clipboard_pane.xml
Normal file
6
res/layout/clipboard_pane.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?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">
|
||||
<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.Keyboard2View layout="@xml/clipboard_bottom_row" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="?attr/colorKeyboard"/>
|
||||
</LinearLayout>
|
4
res/layout/clipboard_pane_entry.xml
Normal file
4
res/layout/clipboard_pane_entry.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?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>
|
@ -115,4 +115,5 @@ Tato aplikace neobsahuje žádné reklamy, nevyužívá připojení k síti a je
|
||||
<string name="key_descr_page_down">Page Down</string>
|
||||
<string name="key_descr_home">Home</string>
|
||||
<string name="key_descr_end">End</string>
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
</resources>
|
||||
|
@ -115,4 +115,5 @@ Diese App enthält keine Werbung, benötigt keinen Netzwerkzugriff und ist quell
|
||||
<string name="key_descr_page_down">Bild ab</string>
|
||||
<string name="key_descr_home">Pos1</string>
|
||||
<string name="key_descr_end">Ende</string>
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
</resources>
|
||||
|
@ -115,4 +115,5 @@ La misma no contiene ningún anuncio/publicidad, no realiza peticiones de red y
|
||||
<string name="key_descr_page_down">Re Pág</string>
|
||||
<string name="key_descr_home">Inicio</string>
|
||||
<string name="key_descr_end">Fin</string>
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
</resources>
|
||||
|
@ -115,4 +115,5 @@ This application contains no ads, doesn't make any network requests and is Open
|
||||
<!-- <string name="key_descr_page_down">Page Down</string> -->
|
||||
<!-- <string name="key_descr_home">Home</string> -->
|
||||
<!-- <string name="key_descr_end">End</string> -->
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
</resources>
|
||||
|
@ -115,4 +115,5 @@ Cette application ne contient pas de publicité, n'accède pas au réseau et est
|
||||
<string name="key_descr_page_down">Page suivante</string>
|
||||
<string name="key_descr_home">Début</string>
|
||||
<string name="key_descr_end">Fin</string>
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
</resources>
|
||||
|
@ -115,4 +115,5 @@ This application contains no ads, doesn't make any network requests and is Open
|
||||
<!-- <string name="key_descr_page_down">Page Down</string> -->
|
||||
<!-- <string name="key_descr_home">Home</string> -->
|
||||
<!-- <string name="key_descr_end">End</string> -->
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
</resources>
|
||||
|
@ -115,4 +115,5 @@ This application contains no ads, doesn't make any network requests and is Open
|
||||
<!-- <string name="key_descr_page_down">Page Down</string> -->
|
||||
<!-- <string name="key_descr_home">Home</string> -->
|
||||
<!-- <string name="key_descr_end">End</string> -->
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
</resources>
|
||||
|
@ -117,4 +117,5 @@ Tagad lieliski piemērota izmantošanai ikdienā.
|
||||
<string name="key_descr_page_down">Lejupšķirt</string>
|
||||
<string name="key_descr_home">Sākums</string>
|
||||
<string name="key_descr_end">Beigas</string>
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
</resources>
|
||||
|
@ -115,4 +115,5 @@ Aplikacja nie zawiera reklam, nie żąda dostępu do internetu, a jej kod źród
|
||||
<string name="key_descr_page_down">Page Down</string>
|
||||
<string name="key_descr_home">Home</string>
|
||||
<string name="key_descr_end">End</string>
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
</resources>
|
||||
|
@ -115,4 +115,5 @@ Este aplicativo não contém anúncios, não faz nenhuma solicitação de rede e
|
||||
<string name="key_descr_page_down">Page Down</string>
|
||||
<string name="key_descr_home">Home</string>
|
||||
<string name="key_descr_end">End</string>
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
</resources>
|
||||
|
@ -115,4 +115,5 @@ Această aplicație nu conține publicitate, nu folosește rețeaua deloc și e
|
||||
<!-- <string name="key_descr_page_down">Page Down</string> -->
|
||||
<!-- <string name="key_descr_home">Home</string> -->
|
||||
<!-- <string name="key_descr_end">End</string> -->
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
</resources>
|
||||
|
@ -115,4 +115,5 @@
|
||||
<string name="key_descr_page_down">Страница вниз</string>
|
||||
<string name="key_descr_home">Home</string>
|
||||
<string name="key_descr_end">End</string>
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
</resources>
|
||||
|
@ -115,4 +115,5 @@ Bu uygulama açık kaynaklıdır. Reklam içermez ve internete bağlanmaz."</str
|
||||
<string name="key_descr_page_down">Aşağı</string>
|
||||
<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> -->
|
||||
</resources>
|
||||
|
@ -115,4 +115,5 @@
|
||||
<string name="key_descr_page_down">Page Down</string>
|
||||
<string name="key_descr_home">Home</string>
|
||||
<string name="key_descr_end">End</string>
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
</resources>
|
||||
|
@ -115,4 +115,5 @@ Bây giờ đã hoàn hảo cho việc sử dụng hàng ngày.
|
||||
<!-- <string name="key_descr_page_down">Page Down</string> -->
|
||||
<!-- <string name="key_descr_home">Home</string> -->
|
||||
<!-- <string name="key_descr_end">End</string> -->
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
</resources>
|
||||
|
@ -115,4 +115,5 @@
|
||||
<string name="key_descr_page_down">下一页</string>
|
||||
<string name="key_descr_home">Home</string>
|
||||
<string name="key_descr_end">End</string>
|
||||
<!-- <string name="clipboard_history_heading">Recently copied text</string> -->
|
||||
</resources>
|
||||
|
@ -115,4 +115,5 @@ This application contains no ads, doesn't make any network requests and is Open
|
||||
<string name="key_descr_page_down">Page Down</string>
|
||||
<string name="key_descr_home">Home</string>
|
||||
<string name="key_descr_end">End</string>
|
||||
<string name="clipboard_history_heading">Recently copied text</string>
|
||||
</resources>
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Emoji pane -->
|
||||
<style name="emojiTypeButton">
|
||||
<item name="android:padding">1px</item>
|
||||
<item name="android:gravity">center</item>
|
||||
@ -15,6 +16,22 @@
|
||||
<item name="android:textSize">@dimen/emoji_text_size</item>
|
||||
<item name="android:textColor">?attr/emoji_color</item>
|
||||
</style>
|
||||
<!-- Clipboard pane -->
|
||||
<style name="clipboardEntry">
|
||||
<item name="android:layout_marginHorizontal">14dp</item>
|
||||
<item name="android:layout_marginVertical">14dp</item>
|
||||
<item name="android:textSize">16dp</item>
|
||||
<item name="android:textColor">?attr/colorLabel</item>
|
||||
</style>
|
||||
<style name="clipboardHeading">
|
||||
<item name="android:layout_marginHorizontal">6dp</item>
|
||||
<item name="android:layout_marginTop">14dp</item>
|
||||
<item name="android:layout_marginBottom">0dp</item>
|
||||
<item name="android:textSize">14dp</item>
|
||||
<item name="android:fontWeight">700</item>
|
||||
<item name="android:textColor">?attr/colorSubLabel</item>
|
||||
</style>
|
||||
<!-- Launcher activity -->
|
||||
<style name="paragraph">
|
||||
<item name="android:layout_width">fill_parent</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
|
@ -23,11 +23,14 @@
|
||||
<attr name="keyBorderColorTop" format="color"/>
|
||||
<attr name="keyBorderColorRight" format="color"/>
|
||||
<attr name="keyBorderColorBottom" format="color"/>
|
||||
<!-- Emoji panel -->
|
||||
<!-- Emoji pane -->
|
||||
<attr name="emoji_button_bg" type="color" format="color"/>
|
||||
<attr name="emoji_color" type="color" format="color"/>
|
||||
<attr name="emoji_key_bg" type="color" format="color"/>
|
||||
<attr name="emoji_key_text" type="color" format="color"/>
|
||||
<!-- Clipboard pane -->
|
||||
<attr name="clipboard_divider_color" type="color" format="color"/>
|
||||
<attr name="clipboard_divider_height" format="dimension"/>
|
||||
<!-- System integration -->
|
||||
<attr name="navigationBarColor" format="color"/>
|
||||
<attr name="windowLightNavigationBar" format="boolean"/>
|
||||
@ -43,6 +46,8 @@
|
||||
<item name="greyedDimming">0.5</item>
|
||||
<item name="emoji_key_bg" type="color">?attr/emoji_button_bg</item>
|
||||
<item name="emoji_key_text" type="color">?attr/colorLabel</item>
|
||||
<item name="clipboard_divider_color" type="color">?attr/colorKey</item>
|
||||
<item name="clipboard_divider_height">1px</item>
|
||||
</style>
|
||||
<style name="Dark" parent="BaseTheme">
|
||||
<item name="android:isLightTheme">false</item>
|
||||
@ -116,6 +121,7 @@
|
||||
<item name="colorSubLabel">#333333</item>
|
||||
<item name="emoji_button_bg">#ffffff</item>
|
||||
<item name="emoji_color">#000000</item>
|
||||
<item name="clipboard_divider_color" type="color">#eeeeee</item>
|
||||
</style>
|
||||
<style name="ePaper" parent="BaseTheme">
|
||||
<item name="android:isLightTheme">true</item>
|
||||
@ -134,6 +140,8 @@
|
||||
<item name="colorSubLabel">#333333</item>
|
||||
<item name="emoji_button_bg">#ffffff</item>
|
||||
<item name="emoji_color">#000000</item>
|
||||
<item name="clipboard_divider_color" type="color">#000000</item>
|
||||
<item name="clipboard_divider_height">2dp</item>
|
||||
</style>
|
||||
<style name="Desert" parent="@style/BaseTheme">
|
||||
<item name="android:isLightTheme">true</item>
|
||||
|
@ -4,6 +4,7 @@
|
||||
<dimen name="key_padding">2dp</dimen>
|
||||
<dimen name="emoji_grid_height">250dp</dimen>
|
||||
<dimen name="emoji_text_size">28dp</dimen>
|
||||
<dimen name="clipboard_view_height">200dp</dimen>
|
||||
<dimen name="pref_button_size">28dp</dimen>
|
||||
<bool name="debug_logs">false</bool> <!-- Will be overwritten automatically by Gradle for the debug build variant -->
|
||||
</resources>
|
||||
|
9
res/xml/clipboard_bottom_row.xml
Normal file
9
res/xml/clipboard_bottom_row.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- The bottom row used in the clipboard history pane. -->
|
||||
<keyboard bottom_row="false">
|
||||
<row height="0.95">
|
||||
<key key0="switch_back_emoji"/>
|
||||
<key shift="4" key0="backspace"/>
|
||||
<key key0="enter"/>
|
||||
</row>
|
||||
</keyboard>
|
85
srcs/juloo.keyboard2/ClipboardHistoryService.java
Normal file
85
srcs/juloo.keyboard2/ClipboardHistoryService.java
Normal file
@ -0,0 +1,85 @@
|
||||
package juloo.keyboard2;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.os.Build.VERSION;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class ClipboardHistoryService
|
||||
{
|
||||
/** Start the service on startup and start listening to clipboard changes. */
|
||||
public static void on_startup(Context ctx)
|
||||
{
|
||||
get_service(ctx);
|
||||
}
|
||||
|
||||
/** Start the service if it hasn't been started before. Returns [null] if the
|
||||
feature is unsupported. */
|
||||
public static ClipboardHistoryService get_service(Context ctx)
|
||||
{
|
||||
if (VERSION.SDK_INT <= 11)
|
||||
return null;
|
||||
if (_service == null)
|
||||
_service = new ClipboardHistoryService(ctx);
|
||||
return _service;
|
||||
}
|
||||
|
||||
/** 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
|
||||
forgotten as soon as the app stops. */
|
||||
public static final int MAX_HISTORY_SIZE = 3;
|
||||
|
||||
static ClipboardHistoryService _service = null;
|
||||
|
||||
ClipboardManager _cm;
|
||||
List<String> _history;
|
||||
OnClipboardHistoryChange _listener = null;
|
||||
|
||||
ClipboardHistoryService(Context ctx)
|
||||
{
|
||||
_history = new ArrayList<String>();
|
||||
_cm = (ClipboardManager)ctx.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
_cm.addPrimaryClipChangedListener(this.new SystemListener());
|
||||
}
|
||||
|
||||
public List<String> get_history() { return _history; }
|
||||
|
||||
/** Add clipboard entries to the history, skipping consecutive duplicates and
|
||||
empty strings. */
|
||||
public void add_clip(String clip)
|
||||
{
|
||||
int size = _history.size();
|
||||
if (clip.equals("") || (size > 0 && _history.get(size - 1).equals(clip)))
|
||||
return;
|
||||
if (size >= MAX_HISTORY_SIZE)
|
||||
_history.remove(0);
|
||||
_history.add(clip);
|
||||
if (_listener != null)
|
||||
_listener.on_clipboard_history_change(_history);
|
||||
}
|
||||
|
||||
public void set_on_clipboard_history_change(OnClipboardHistoryChange l) { _listener = l; }
|
||||
|
||||
public static interface OnClipboardHistoryChange
|
||||
{
|
||||
public void on_clipboard_history_change(List<String> history);
|
||||
}
|
||||
|
||||
final class SystemListener implements ClipboardManager.OnPrimaryClipChangedListener
|
||||
{
|
||||
public SystemListener() {}
|
||||
|
||||
@Override
|
||||
public void onPrimaryClipChanged()
|
||||
{
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
78
srcs/juloo.keyboard2/ClipboardHistoryView.java
Normal file
78
srcs/juloo.keyboard2/ClipboardHistoryView.java
Normal file
@ -0,0 +1,78 @@
|
||||
package juloo.keyboard2;
|
||||
|
||||
import android.content.Context;
|
||||
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;
|
||||
|
||||
public final class ClipboardHistoryView extends ListView
|
||||
implements ClipboardHistoryService.OnClipboardHistoryChange
|
||||
{
|
||||
List<String> _history;
|
||||
ClipboardEntriesAdapter _adapter;
|
||||
|
||||
public ClipboardHistoryView(Context ctx, AttributeSet attrs)
|
||||
{
|
||||
super(ctx, attrs);
|
||||
_history = Collections.EMPTY_LIST;
|
||||
_adapter = this.new ClipboardEntriesAdapter();
|
||||
ClipboardHistoryService service = ClipboardHistoryService.get_service(ctx);
|
||||
if (service != null)
|
||||
{
|
||||
service.set_on_clipboard_history_change(this);
|
||||
_history = service.get_history();
|
||||
}
|
||||
setAdapter(_adapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void on_clipboard_history_change(List<String> history)
|
||||
{
|
||||
_history = history;
|
||||
_adapter.notifyDataSetChanged();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow()
|
||||
{
|
||||
super.onAttachedToWindow();
|
||||
_adapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
class ClipboardEntriesAdapter extends BaseAdapter
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(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));
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
@ -12,6 +12,8 @@ public final class KeyValue implements Comparable<KeyValue>
|
||||
SWITCH_NUMERIC,
|
||||
SWITCH_EMOJI,
|
||||
SWITCH_BACK_EMOJI,
|
||||
SWITCH_CLIPBOARD,
|
||||
SWITCH_BACK_CLIPBOARD,
|
||||
CHANGE_METHOD_PICKER,
|
||||
CHANGE_METHOD_AUTO,
|
||||
ACTION,
|
||||
@ -460,6 +462,8 @@ public final class KeyValue implements Comparable<KeyValue>
|
||||
case "switch_numeric": return eventKey("123+", Event.SWITCH_NUMERIC, FLAG_SMALLER_FONT);
|
||||
case "switch_emoji": return eventKey(0xE001, Event.SWITCH_EMOJI, FLAG_SMALLER_FONT);
|
||||
case "switch_back_emoji": return eventKey("ABC", Event.SWITCH_BACK_EMOJI, 0);
|
||||
case "switch_clipboard": return eventKey("Clip", Event.SWITCH_CLIPBOARD, FLAG_SMALLER_FONT);
|
||||
case "switch_back_clipboard": return eventKey("ABC", Event.SWITCH_BACK_CLIPBOARD, 0);
|
||||
case "switch_forward": return eventKey(0xE013, Event.SWITCH_FORWARD, FLAG_SMALLER_FONT);
|
||||
case "switch_backward": return eventKey(0xE014, Event.SWITCH_BACKWARD, FLAG_SMALLER_FONT);
|
||||
case "switch_greekmath": return eventKey("πλ∇¬", Event.SWITCH_GREEKMATH, FLAG_SMALLER_FONT);
|
||||
|
@ -36,6 +36,7 @@ public class Keyboard2 extends InputMethodService
|
||||
/** Layout associated with the currently selected locale. Not 'null'. */
|
||||
private KeyboardData _localeTextLayout;
|
||||
private ViewGroup _emojiPane = null;
|
||||
private ViewGroup _clipboard_pane = null;
|
||||
public int actionId; // Action performed by the Action key.
|
||||
|
||||
private Config _config;
|
||||
@ -113,6 +114,7 @@ public class Keyboard2 extends InputMethodService
|
||||
_keyboardView = (Keyboard2View)inflate_view(R.layout.keyboard);
|
||||
_keyboardView.reset();
|
||||
Logs.set_debug_logs(getResources().getBoolean(R.bool.debug_logs));
|
||||
ClipboardHistoryService.on_startup(this);
|
||||
}
|
||||
|
||||
private List<InputMethodSubtype> getEnabledSubtypes(InputMethodManager imm)
|
||||
@ -223,6 +225,7 @@ public class Keyboard2 extends InputMethodService
|
||||
{
|
||||
_keyboardView = (Keyboard2View)inflate_view(R.layout.keyboard);
|
||||
_emojiPane = null;
|
||||
_clipboard_pane = null;
|
||||
setInputView(_keyboardView);
|
||||
}
|
||||
_keyboardView.reset();
|
||||
@ -384,7 +387,14 @@ public class Keyboard2 extends InputMethodService
|
||||
setInputView(_emojiPane);
|
||||
break;
|
||||
|
||||
case SWITCH_CLIPBOARD:
|
||||
if (_clipboard_pane == null)
|
||||
_clipboard_pane = (ViewGroup)inflate_view(R.layout.clipboard_pane);
|
||||
setInputView(_clipboard_pane);
|
||||
break;
|
||||
|
||||
case SWITCH_BACK_EMOJI:
|
||||
case SWITCH_BACK_CLIPBOARD:
|
||||
setInputView(_keyboardView);
|
||||
break;
|
||||
|
||||
|
@ -24,6 +24,7 @@ public class ExtraKeysPreference extends PreferenceCategory
|
||||
"meta",
|
||||
"compose",
|
||||
"voice_typing",
|
||||
"switch_clipboard",
|
||||
"accent_aigu",
|
||||
"accent_grave",
|
||||
"accent_double_aigu",
|
||||
|
Loading…
Reference in New Issue
Block a user