Fix Emoji recents

Bug: 10538430

Change-Id: Ia2e423eb1843195b3c3218afc79a5820b8cd729b
main
Satoshi Kataoka 2013-09-18 14:24:42 +09:00
parent d2cafb0305
commit ea7bfa5cd5
6 changed files with 136 additions and 25 deletions

View File

@ -505,10 +505,7 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
@Override @Override
public void onKeyClick(final Key key) { public void onKeyClick(final Key key) {
// TODO: Save emoticons to recents mEmojiKeyboardAdapter.addRecentKey(key);
if (mEmojiCategory.getCurrentCategoryId() != CATEGORY_ID_EMOTICONS) {
mEmojiKeyboardAdapter.addRecentKey(key);
}
mEmojiCategory.saveLastTypedCategoryPage(); mEmojiCategory.saveLastTypedCategoryPage();
final int code = key.getCode(); final int code = key.getCode();
if (code == Constants.CODE_OUTPUT_TEXT) { if (code == Constants.CODE_OUTPUT_TEXT) {

View File

@ -155,6 +155,15 @@ public class Keyboard {
return mKeys; return mKeys;
} }
public Key getKeyFromOutputText(final String outputText) {
for (final Key key : getKeys()) {
if (outputText.equals(key.getOutputText())) {
return key;
}
}
return null;
}
public Key getKey(final int code) { public Key getKey(final int code) {
if (code == Constants.CODE_UNSPECIFIED) { if (code == Constants.CODE_UNSPECIFIED) {
return null; return null;

View File

@ -18,25 +18,27 @@ package com.android.inputmethod.keyboard.internal;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log;
import com.android.inputmethod.keyboard.EmojiKeyboardView; import com.android.inputmethod.keyboard.EmojiKeyboardView;
import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.settings.Settings; import com.android.inputmethod.latin.settings.Settings;
import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.CollectionUtils;
import com.android.inputmethod.latin.utils.StringUtils;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List;
/** /**
* This is a Keyboard class where you can add keys dynamically shown in a grid layout * This is a Keyboard class where you can add keys dynamically shown in a grid layout
*/ */
public class DynamicGridKeyboard extends Keyboard { public class DynamicGridKeyboard extends Keyboard {
private static final String TAG = DynamicGridKeyboard.class.getSimpleName();
private static final int TEMPLATE_KEY_CODE_0 = 0x30; private static final int TEMPLATE_KEY_CODE_0 = 0x30;
private static final int TEMPLATE_KEY_CODE_1 = 0x31; private static final int TEMPLATE_KEY_CODE_1 = 0x31;
// Recent codes are saved as an integer array, so we use comma as a separater.
private static final String RECENT_KEY_SEPARATOR = Constants.STRING_COMMA;
private final SharedPreferences mPrefs; private final SharedPreferences mPrefs;
private final int mLeftPadding; private final int mLeftPadding;
@ -84,6 +86,9 @@ public class DynamicGridKeyboard extends Keyboard {
} }
private void addKey(final Key usedKey, final boolean addFirst) { private void addKey(final Key usedKey, final boolean addFirst) {
if (usedKey == null) {
return;
}
synchronized (mGridKeys) { synchronized (mGridKeys) {
mCachedGridKeys = null; mCachedGridKeys = null;
final GridKey key = new GridKey(usedKey); final GridKey key = new GridKey(usedKey);
@ -109,27 +114,44 @@ public class DynamicGridKeyboard extends Keyboard {
} }
private void saveRecentKeys() { private void saveRecentKeys() {
final StringBuilder sb = new StringBuilder(); final ArrayList<Object> keys = CollectionUtils.newArrayList();
for (final Key key : mGridKeys) { for (final Key key : mGridKeys) {
sb.append(key.getCode()).append(RECENT_KEY_SEPARATOR); if (key.getOutputText() != null) {
keys.add(key.getOutputText());
} else {
keys.add(key.getCode());
}
} }
Settings.writeEmojiRecentKeys(mPrefs, sb.toString()); final String jsonStr = StringUtils.listToJsonStr(keys);
Settings.writeEmojiRecentKeys(mPrefs, jsonStr);
}
private static Key getKey(final Collection<DynamicGridKeyboard> keyboards, final Object o) {
for (final DynamicGridKeyboard kbd : keyboards) {
if (o instanceof Integer) {
final int code = (Integer) o;
final Key key = kbd.getKey(code);
if (key != null) {
return key;
}
} else if (o instanceof String) {
final String outputText = (String) o;
final Key key = kbd.getKeyFromOutputText(outputText);
if (key != null) {
return key;
}
} else {
Log.w(TAG, "Invalid object: " + o);
}
}
return null;
} }
public void loadRecentKeys(Collection<DynamicGridKeyboard> keyboards) { public void loadRecentKeys(Collection<DynamicGridKeyboard> keyboards) {
final String str = Settings.readEmojiRecentKeys(mPrefs); final String str = Settings.readEmojiRecentKeys(mPrefs);
for (String s : str.split(RECENT_KEY_SEPARATOR)) { final List<Object> keys = StringUtils.jsonStrToList(str);
if (TextUtils.isEmpty(s)) { for (final Object o : keys) {
continue; addKeyLast(getKey(keyboards, o));
}
final int code = Integer.valueOf(s);
for (DynamicGridKeyboard kbd : keyboards) {
final Key key = kbd.getKey(code);
if (key != null) {
addKeyLast(key);
break;
}
}
} }
} }

View File

@ -221,7 +221,6 @@ public final class Constants {
} }
public static final int MAX_INT_BIT_COUNT = 32; public static final int MAX_INT_BIT_COUNT = 32;
public static final String STRING_COMMA = ",";
private Constants() { private Constants() {
// This utility class is not publicly instantiable. // This utility class is not publicly instantiable.

View File

@ -16,16 +16,25 @@
package com.android.inputmethod.latin.utils; package com.android.inputmethod.latin.utils;
import android.text.TextUtils;
import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.settings.SettingsValues; import com.android.inputmethod.latin.settings.SettingsValues;
import android.text.TextUtils;
import android.util.JsonReader;
import android.util.JsonWriter;
import android.util.Log;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale; import java.util.Locale;
public final class StringUtils { public final class StringUtils {
private static final String TAG = StringUtils.class.getSimpleName();
public static final int CAPITALIZE_NONE = 0; // No caps, or mixed case public static final int CAPITALIZE_NONE = 0; // No caps, or mixed case
public static final int CAPITALIZE_FIRST = 1; // First only public static final int CAPITALIZE_FIRST = 1; // First only
public static final int CAPITALIZE_ALL = 2; // All caps public static final int CAPITALIZE_ALL = 2; // All caps
@ -390,4 +399,67 @@ public final class StringUtils {
} }
return bytes; return bytes;
} }
public static List<Object> jsonStrToList(String s) {
final ArrayList<Object> retval = CollectionUtils.newArrayList();
final JsonReader reader = new JsonReader(new StringReader(s));
try {
reader.beginArray();
while(reader.hasNext()) {
reader.beginObject();
while (reader.hasNext()) {
final String name = reader.nextName();
if (name.equals(Integer.class.getSimpleName())) {
retval.add(reader.nextInt());
} else if (name.equals(String.class.getSimpleName())) {
retval.add(reader.nextString());
} else {
Log.w(TAG, "Invalid name: " + name);
reader.skipValue();
}
}
reader.endObject();
}
reader.endArray();
return retval;
} catch (IOException e) {
} finally {
try {
reader.close();
} catch (IOException e) {
}
}
return Collections.<Object>emptyList();
}
public static String listToJsonStr(List<Object> list) {
if (list == null || list.isEmpty()) {
return "";
}
final StringWriter sw = new StringWriter();
final JsonWriter writer = new JsonWriter(sw);
try {
writer.beginArray();
for (final Object o : list) {
writer.beginObject();
if (o instanceof Integer) {
writer.name(Integer.class.getSimpleName()).value((Integer)o);
} else if (o instanceof String) {
writer.name(String.class.getSimpleName()).value((String)o);
}
writer.endObject();
}
writer.endArray();
return sw.toString();
} catch (IOException e) {
} finally {
try {
if (writer != null) {
writer.close();
}
} catch (IOException e) {
}
}
return "";
}
} }

View File

@ -21,6 +21,8 @@ import com.android.inputmethod.latin.settings.SettingsValues;
import android.test.AndroidTestCase; import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest; import android.test.suitebuilder.annotation.SmallTest;
import java.util.Arrays;
import java.util.List;
import java.util.Locale; import java.util.Locale;
@SmallTest @SmallTest
@ -268,4 +270,14 @@ public class StringUtilsTests extends AndroidTestCase {
final String bytesStr2 = StringUtils.byteArrayToHexString(bytes2); final String bytesStr2 = StringUtils.byteArrayToHexString(bytes2);
assertTrue(bytesStr.equals(bytesStr2)); assertTrue(bytesStr.equals(bytesStr2));
} }
public void testJsonStringUtils() {
final Object[] objs = new Object[] { 1, "aaa", "bbb", 3 };
final List<Object> objArray = Arrays.asList(objs);
final String str = StringUtils.listToJsonStr(objArray);
final List<Object> newObjArray = StringUtils.jsonStrToList(str);
for (int i = 0; i < objs.length; ++i) {
assertEquals(objs[i], newObjArray.get(i));
}
}
} }