diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0f20a45b1..5cac97c82 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -103,4 +103,8 @@ dependencies { implementation(libs.bundles.room) ksp(libs.androidx.room.compiler) + + implementation (project(":emojipicker")) + + } diff --git a/app/src/main/kotlin/com/simplemobiletools/keyboard/helpers/OtherInputConnection.kt b/app/src/main/kotlin/com/simplemobiletools/keyboard/helpers/OtherInputConnection.kt new file mode 100644 index 000000000..1eaf83bfc --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/keyboard/helpers/OtherInputConnection.kt @@ -0,0 +1,197 @@ +package com.simplemobiletools.keyboard.helpers; + +import android.os.Bundle +import android.text.Editable +import android.text.Spanned +import android.text.style.SuggestionSpan +import android.util.Log +import android.view.inputmethod.BaseInputConnection +import android.view.inputmethod.CompletionInfo +import android.view.inputmethod.CorrectionInfo +import android.view.inputmethod.ExtractedText +import android.view.inputmethod.ExtractedTextRequest +import android.widget.SearchView +import android.widget.TextView + +/** + * Source: https://stackoverflow.com/a/39460124 + */ +class OtherInputConnection(private val mTextView: androidx.appcompat.widget.AppCompatAutoCompleteTextView?) : BaseInputConnection( + mTextView!!, true +) { + // Keeps track of nested begin/end batch edit to ensure this connection always has a + // balanced impact on its associated TextView. + // A negative value means that this connection has been finished by the InputMethodManager. + private var mBatchEditNesting = 0 + + + override fun getEditable(): Editable? { + val tv = mTextView + Log.i("heregotEditTEZT", tv!!.text.toString()) + return tv?.editableText + } + + + + override fun beginBatchEdit(): Boolean { + synchronized(this) { + if (mBatchEditNesting >= 0) { + mTextView!!.beginBatchEdit() + mBatchEditNesting++ + return true + } + } + return false + } + + override fun endBatchEdit(): Boolean { + synchronized(this) { + if (mBatchEditNesting > 0) { + // When the connection is reset by the InputMethodManager and reportFinish + // is called, some endBatchEdit calls may still be asynchronously received from the + // IME. Do not take these into account, thus ensuring that this IC's final + // contribution to mTextView's nested batch edit count is zero. + mTextView!!.endBatchEdit() + mBatchEditNesting-- + return true + } + } + return false + } + + //clear the meta key states means shift, alt, ctrl + override fun clearMetaKeyStates(states: Int): Boolean { + val content = editable ?: return false + val kl = mTextView!!.keyListener //listen keyevents like a, enter, space + if (kl != null) { + try { + kl.clearMetaKeyState(mTextView, content, states) + } catch (e: AbstractMethodError) { + // This is an old listener that doesn't implement the + // new method. + } + } + return true + } + + //When a user selects a suggestion from an autocomplete or suggestion list, the input method may call commitCompletion + override fun commitCompletion(text: CompletionInfo): Boolean { + if (DEBUG) Log.v( + TAG, + "commitCompletion $text" + ) + mTextView!!.beginBatchEdit() + mTextView.onCommitCompletion(text) + mTextView.endBatchEdit() + return true + } + + /** + which is used to commit a correction to a previously entered text. + This correction could be suggested by the input method or obtained through some other means. + */ + override fun commitCorrection(correctionInfo: CorrectionInfo): Boolean { + if (DEBUG) Log.v( + TAG, + "commitCorrection$correctionInfo" + ) + mTextView!!.beginBatchEdit() + mTextView.onCommitCorrection(correctionInfo) + mTextView.endBatchEdit() + return true + } + + /* It's used to simulate the action associated with an editor action, typically triggered by pressing the "Done" or "Enter" key on the keyboard.*/ + override fun performEditorAction(actionCode: Int): Boolean { + if (DEBUG) Log.v( + TAG, + "performEditorAction $actionCode" + ) + mTextView!!.onEditorAction(actionCode) + return true + } + +/* + handle actions triggered from the context menu associated with the search text. + This menu typically appears when you long-press on the search text field. +*/ + override fun performContextMenuAction(id: Int): Boolean { + if (DEBUG) Log.v( + TAG, + "performContextMenuAction $id" + ) + mTextView!!.beginBatchEdit() + mTextView.onTextContextMenuItem(id) + mTextView.endBatchEdit() + return true + } + + /*It is used to retrieve information about the currently extracted text + * eg- selected text, the start and end offsets, the total number of characters, and more.*/ + override fun getExtractedText(request: ExtractedTextRequest, flags: Int): ExtractedText? { + if (mTextView != null) { + val et = ExtractedText() + if (mTextView.extractText(request, et)) { + if (flags and GET_EXTRACTED_TEXT_MONITOR != 0) { +// mTextView.setExtracting(request); + } + return et + } + } + return null + } + +// API to send private commands from an input method to its connected editor. This can be used to provide domain-specific features + override fun performPrivateCommand(action: String, data: Bundle): Boolean { + mTextView!!.onPrivateIMECommand(action, data) + return true + } + + //send the text to the connected editor from the keyboard pressed + override fun commitText( + text: CharSequence, + newCursorPosition: Int + ): Boolean { + if (mTextView == null) { + return super.commitText(text, newCursorPosition) + } + if (text is Spanned) { + val spans = text.getSpans( + 0, text.length, + SuggestionSpan::class.java + ) + // mIMM.registerSuggestionSpansForNotification(spans); + } + +// mTextView.resetErrorChangedFlag(); + // mTextView.hideErrorIfUnchanged(); + return super.commitText(text, newCursorPosition) + } + + override fun requestCursorUpdates(cursorUpdateMode: Int): Boolean { + if (DEBUG) Log.v( + TAG, + "requestUpdateCursorAnchorInfo $cursorUpdateMode" + ) + + // It is possible that any other bit is used as a valid flag in a future release. + // We should reject the entire request in such a case. + val KNOWN_FLAGS_MASK = CURSOR_UPDATE_IMMEDIATE or CURSOR_UPDATE_MONITOR + val unknownFlags = cursorUpdateMode and KNOWN_FLAGS_MASK.inv() + if (unknownFlags != 0) { + if (DEBUG) { + Log.d( + TAG, + "Rejecting requestUpdateCursorAnchorInfo due to unknown flags. cursorUpdateMode=$cursorUpdateMode unknownFlags=$unknownFlags" + ) + } + return false + } + return false + } + + companion object { + private const val DEBUG = false + private val TAG = "loool" + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/keyboard/interfaces/OnKeyboardActionListener.kt b/app/src/main/kotlin/com/simplemobiletools/keyboard/interfaces/OnKeyboardActionListener.kt index 73ca5b9ae..191ba7796 100644 --- a/app/src/main/kotlin/com/simplemobiletools/keyboard/interfaces/OnKeyboardActionListener.kt +++ b/app/src/main/kotlin/com/simplemobiletools/keyboard/interfaces/OnKeyboardActionListener.kt @@ -41,4 +41,9 @@ interface OnKeyboardActionListener { * Called to force the KeyboardView to reload the keyboard */ fun reloadKeyboard() + + /* + * called when focus on the searchview */ + fun searchViewFocused(searchView: androidx.appcompat.widget.AppCompatAutoCompleteTextView) + } diff --git a/app/src/main/kotlin/com/simplemobiletools/keyboard/services/SimpleKeyboardIME.kt b/app/src/main/kotlin/com/simplemobiletools/keyboard/services/SimpleKeyboardIME.kt index 500b08da3..3f4728262 100644 --- a/app/src/main/kotlin/com/simplemobiletools/keyboard/services/SimpleKeyboardIME.kt +++ b/app/src/main/kotlin/com/simplemobiletools/keyboard/services/SimpleKeyboardIME.kt @@ -13,6 +13,7 @@ import android.os.Build import android.os.Bundle import android.text.InputType.* import android.text.TextUtils +import android.util.Log import android.util.Size import android.view.KeyEvent import android.view.View @@ -23,6 +24,8 @@ import android.view.inputmethod.EditorInfo.IME_FLAG_NO_ENTER_ACTION import android.view.inputmethod.EditorInfo.IME_MASK_ACTION import android.widget.inline.InlinePresentationSpec import androidx.annotation.RequiresApi +import androidx.appcompat.widget.AppCompatAutoCompleteTextView +import androidx.appcompat.widget.SearchView import androidx.autofill.inline.UiVersions import androidx.autofill.inline.common.ImageViewStyle import androidx.autofill.inline.common.TextViewStyle @@ -60,9 +63,17 @@ class SimpleKeyboardIME : InputMethodService(), OnKeyboardActionListener, Shared private var enterKeyType = IME_ACTION_NONE private var switchToLetters = false private var breakIterator: BreakIterator? = null + private var otherInputConnection:OtherInputConnection? = null private lateinit var binding: KeyboardViewKeyboardBinding + companion object{ + /*true and false define the inputconnection where is input is send like + * if true-> send to emoji searchview + * if false -> send to currentinputconnection*/ + var searching=false + } + override fun onInitializeInterface() { super.onInitializeInterface() safeStorageContext.getSharedPrefs().registerOnSharedPreferenceChangeListener(this) @@ -106,7 +117,7 @@ class SimpleKeyboardIME : InputMethodService(), OnKeyboardActionListener, Shared val editorInfo = currentInputEditorInfo if (config.enableSentencesCapitalization && editorInfo != null && editorInfo.inputType != TYPE_NULL) { - if (currentInputConnection.getCursorCapsMode(editorInfo.inputType) != 0) { + if (currentInputConnection.getCursorCapsMode(editorInfo.inputType) != 0 && !searching) { keyboard?.setShifted(ShiftState.ON_ONE_CHAR) keyboardView?.invalidateAllKeys() return @@ -149,7 +160,7 @@ class SimpleKeyboardIME : InputMethodService(), OnKeyboardActionListener, Shared } override fun onKey(code: Int) { - val inputConnection = currentInputConnection + val inputConnection = getMyCurrentInputConnection() if (keyboard == null || inputConnection == null) { return } @@ -216,7 +227,10 @@ class SimpleKeyboardIME : InputMethodService(), OnKeyboardActionListener, Shared } MyKeyboard.KEYCODE_EMOJI -> { - keyboardView?.openEmojiPalette() + if(!searching){ + keyboardView?.openEmojiPalette() + } + } else -> { @@ -324,7 +338,8 @@ class SimpleKeyboardIME : InputMethodService(), OnKeyboardActionListener, Shared } override fun onText(text: String) { - currentInputConnection?.commitText(text, 1) + getMyCurrentInputConnection().commitText(text, 1) + } override fun reloadKeyboard() { @@ -333,6 +348,10 @@ class SimpleKeyboardIME : InputMethodService(), OnKeyboardActionListener, Shared keyboardView?.setKeyboard(keyboard) } + override fun searchViewFocused(searchView: AppCompatAutoCompleteTextView) { + otherInputConnection = OtherInputConnection(searchView) + } + private fun createNewKeyboard(): MyKeyboard { val keyboardXml = when (inputTypeClass) { TYPE_CLASS_NUMBER -> { @@ -485,4 +504,20 @@ class SimpleKeyboardIME : InputMethodService(), OnKeyboardActionListener, Shared return Icon.createWithData(byteArray, 0, byteArray.size) } + + fun getMyCurrentInputConnection():InputConnection{ + if (searching){ + if(otherInputConnection==null){ + Log.i("thisISrunn", "yes2") + return currentInputConnection + }else{ + Log.i("thisISrunn", "yes") + return otherInputConnection!! + } + + }else{ + Log.i("thisISrunn", "yes3") + return currentInputConnection + } + } } diff --git a/app/src/main/kotlin/com/simplemobiletools/keyboard/views/MyKeyboardView.kt b/app/src/main/kotlin/com/simplemobiletools/keyboard/views/MyKeyboardView.kt index 4caeb5b45..be1c28e63 100644 --- a/app/src/main/kotlin/com/simplemobiletools/keyboard/views/MyKeyboardView.kt +++ b/app/src/main/kotlin/com/simplemobiletools/keyboard/views/MyKeyboardView.kt @@ -15,7 +15,11 @@ import android.os.Build import android.os.Handler import android.os.Looper import android.os.Message +import android.text.Editable +import android.text.Html +import android.text.TextWatcher import android.util.AttributeSet +import android.util.Log import android.util.TypedValue import android.view.* import android.view.animation.AccelerateInterpolator @@ -34,6 +38,7 @@ import androidx.emoji2.text.EmojiCompat.EMOJI_SUPPORTED import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup import androidx.recyclerview.widget.LinearLayoutManager +import com.rishabh.emojipicker.EmojiPickerView import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.isPiePlus @@ -60,6 +65,7 @@ import com.simplemobiletools.keyboard.interfaces.RefreshClipsListener import com.simplemobiletools.keyboard.models.Clip import com.simplemobiletools.keyboard.models.ClipsSectionLabel import com.simplemobiletools.keyboard.models.ListItem +import com.simplemobiletools.keyboard.services.SimpleKeyboardIME.Companion.searching import java.util.* @SuppressLint("UseCompatLoadingForDrawables", "ClickableViewAccessibility") @@ -258,7 +264,7 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut super.onVisibilityChanged(changedView, visibility) closeClipboardManager() closeEmojiPalette() - + keyboardViewBinding?.emojiPaletteHolder?.beGone() if (visibility == VISIBLE) { setupKeyboard(changedView) } @@ -273,6 +279,8 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut showPreview(NOT_A_KEY) } + keyboardViewBinding?.emojiPaletteHolder?.beGone() + closeClipboardManager() removeMessages() mKeyboard = keyboard @@ -288,6 +296,7 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut accessHelper = AccessHelper(this, mKeyboard?.mKeys.orEmpty()) ViewCompat.setAccessibilityDelegate(this, accessHelper) + // Not really necessary to do every time, but will free up views // Switching to a different keyboard should abort any pending keys so that the key up // doesn't get delivered to the old or new keyboard @@ -297,7 +306,7 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut /** Sets the top row above the keyboard containing a couple buttons and the clipboard **/ fun setKeyboardHolder(binding: KeyboardViewKeyboardBinding) { keyboardViewBinding = binding.apply { - mToolbarHolder = toolbarHolder + mToolbarHolder = mainToolbarKeyboardHolder mClipboardManagerHolder = clipboardManagerHolder mEmojiPaletteHolder = emojiPaletteHolder @@ -354,10 +363,7 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut } } - emojiPaletteClose.setOnClickListener { - vibrateIfNeeded() - closeEmojiPalette() - } + } } @@ -1439,10 +1445,19 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut private fun setupEmojiPalette(toolbarColor: Int, backgroundColor: Int, textColor: Int) { keyboardViewBinding?.apply { - emojiPaletteTopBar.background = ColorDrawable(toolbarColor) + emojiSearchToolbar.background = ColorDrawable(toolbarColor) emojiPaletteHolder.background = ColorDrawable(backgroundColor) emojiPaletteClose.applyColorFilter(textColor) - emojiPaletteLabel.setTextColor(textColor) + + emojiSearchView.setHintTextColor(mTextColor) + emojiSearchviewCross.applyColorFilter(textColor) + emojiSearchViewSearchIcon.applyColorFilter(textColor) + emojiSearchResult.background = ColorDrawable(backgroundColor) + + + + + emojiPaletteBottomBar.background = ColorDrawable(backgroundColor) emojiPaletteModeChange.apply { @@ -1481,37 +1496,108 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut } } } - - setupEmojis() } + fun openEmojiPalette() { keyboardViewBinding!!.emojiPaletteHolder.beVisible() - setupEmojis() - } + keyboardViewBinding!!.emojiSearchToolbar.beVisible() + keyboardViewBinding!!.mainToolbarKeyboardHolder.beGone() + + /*when any emoji is picked from the emoji Picker*/ + keyboardViewBinding!!.emojiPickerView.setOnEmojiPickedListener{ + mOnKeyboardActionListener?.onText(it.emoji) + - private fun closeEmojiPalette() { - keyboardViewBinding?.apply { - emojiPaletteHolder.beGone() - emojisList?.scrollToPosition(0) } + + setupEmojiSearch() } - private fun setupEmojis() { - ensureBackgroundThread { - val fullEmojiList = parseRawEmojiSpecsFile(context, EMOJI_SPEC_FILE_PATH) - val systemFontPaint = Paint().apply { - typeface = Typeface.DEFAULT + + + private fun setupEmojiSearch(){ + keyboardViewBinding?.apply { + emojiSearchView.setOnFocusChangeListener(object : View.OnFocusChangeListener{ + override fun onFocusChange(v: View?, hasFocus: Boolean) { + emojiPaletteHolder.beGone() + mainToolbarKeyboardHolder.beGone() +// emojiSearchView.text.clear() + + //change the input connection + searching=true + mOnKeyboardActionListener?.searchViewFocused(emojiSearchView) + + //show emoji result + emojiSearchResult.beVisible() + + + /*It's s interface it runn when someone picked ffrom the emoji search result suggestion*/ + val emojipickedFromSuggestion= object : EmojiPickerView.EmojiPickedFromSuggestion { + override fun pickedEmoji(emoji: String) { + searching =false + mOnKeyboardActionListener?.onText(emoji) + searching =true + } + } + + emojiSearchResult.emojiPickedFromSuggestion = (emojipickedFromSuggestion) + + + /*when nothing is typed then in the showSearchResult show the recend only*/ + keyboardViewBinding?.apply { + emojiSearchResult.bodyAdapter.hideTitleAndEmptyHint = true + emojiSearchResult.emojiPickerItems = emojiSearchResult.buildEmojiPickerItems(onlyRecentEmojies = true) + emojiSearchResult.bodyAdapter.notifyDataSetChanged() + } + + } + }) + + + + emojiPaletteClose.setOnClickListener { + vibrateIfNeeded() + closeEmojiPalette() } - val emojis = fullEmojiList.filter { emoji -> - systemFontPaint.hasGlyph(emoji.emoji) || (EmojiCompat.get().loadState == EmojiCompat.LOAD_STATE_SUCCEEDED && EmojiCompat.get() - .getEmojiMatch(emoji.emoji, emojiCompatMetadataVersion) == EMOJI_SUPPORTED) + emojiSearchviewCross.setOnClickListener { + emojiSearchView.text.clear() } - Handler(Looper.getMainLooper()).post { - setupEmojiAdapter(emojis) + emojiSearchView.addTextChangedListener(object:TextWatcher{ + override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} + + override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {} + + override fun afterTextChanged(s: Editable?) { + emojiSearchResult.emojiPickerItems = emojiSearchResult.buildEmojiPickerItems(false,s.toString()) + emojiSearchResult.bodyAdapter.notifyDataSetChanged() + } + + }) + } + } + + private fun closeEmojiPalette() { + + keyboardViewBinding?.apply { + + + if(emojiPaletteHolder.isVisible){ + Log.i("thisISsRUNN","YESS") + emojiPaletteHolder.beGone() + emojiSearchToolbar.beGone() + mainToolbarKeyboardHolder.beVisible() + }else{ + Log.i("thisISsRUNN","YESS2") + emojiSearchView.clearFocus() + emojiSearchView.text.clear() + emojiPaletteHolder.beVisible() } + + searching =false + keyboardViewBinding?.emojiSearchResult?.beGone() } } @@ -1522,83 +1608,7 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut } } - private fun setupEmojiAdapter(emojis: List) { - val categories = emojis.groupBy { it.category } - val allItems = mutableListOf() - categories.entries.forEach { (category, emojis) -> - allItems.add(EmojisAdapter.Item.Category(category)) - allItems.addAll(emojis.map(EmojisAdapter.Item::Emoji)) - } - val checkIds = mutableMapOf() - keyboardViewBinding?.emojiCategoriesStrip?.apply { - weightSum = categories.count().toFloat() - val strip = this - removeAllViews() - categories.entries.forEach { (category, emojis) -> - ItemEmojiCategoryBinding.inflate(LayoutInflater.from(context), this, true).apply { - root.id = generateViewId() - checkIds[root.id] = category - root.setImageResource(emojis.first().getCategoryIcon()) - root.layoutParams = LinearLayout.LayoutParams( - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.MATCH_PARENT, - 1f - ) - root.setOnClickListener { - strip.children.filterIsInstance().forEach { - it.imageTintList = ColorStateList.valueOf(mTextColor) - } - root.imageTintList = ColorStateList.valueOf(context.getProperPrimaryColor()) - keyboardViewBinding?.emojisList?.stopScroll() - (keyboardViewBinding?.emojisList?.layoutManager as? GridLayoutManager)?.scrollToPositionWithOffset( - allItems.indexOfFirst { it is EmojisAdapter.Item.Category && it.value == category }, - 0 - ) - } - root.imageTintList = ColorStateList.valueOf(mTextColor) - } - } - } - keyboardViewBinding?.emojisList?.apply { - val emojiItemWidth = context.resources.getDimensionPixelSize(R.dimen.emoji_item_size) - val emojiTopBarElevation = context.resources.getDimensionPixelSize(R.dimen.emoji_top_bar_elevation).toFloat() - - layoutManager = AutoGridLayoutManager(context, emojiItemWidth).apply { - spanSizeLookup = object : SpanSizeLookup() { - override fun getSpanSize(position: Int): Int = - if (allItems[position] is EmojisAdapter.Item.Category) { - spanCount - } else { - 1 - } - } - } - adapter = EmojisAdapter(context = context, items = allItems) { emoji -> - mOnKeyboardActionListener!!.onText(emoji.emoji) - vibrateIfNeeded() - } - clearOnScrollListeners() - onScroll { - keyboardViewBinding!!.emojiPaletteTopBar.elevation = if (it > 4) emojiTopBarElevation else 0f - (keyboardViewBinding?.emojisList?.layoutManager as? LinearLayoutManager)?.findFirstCompletelyVisibleItemPosition()?.also { firstVisibleIndex -> - allItems - .withIndex() - .lastOrNull { it.value is EmojisAdapter.Item.Category && it.index <= firstVisibleIndex } - ?.also { activeCategory -> - val id = checkIds.entries.first { it.value == (activeCategory.value as EmojisAdapter.Item.Category).value }.key - keyboardViewBinding?.emojiCategoriesStrip?.children?.filterIsInstance()?.forEach { - if (it.id == id) { - it.imageTintList = ColorStateList.valueOf(context.getProperPrimaryColor()) - } else { - it.imageTintList = ColorStateList.valueOf(mTextColor) - } - } - } - } - } - } - } private fun closing() { if (mPreviewPopup.isShowing) { diff --git a/app/src/main/res/layout/emoji_list.xml b/app/src/main/res/layout/emoji_list.xml index 5baf16714..a8966f25f 100644 --- a/app/src/main/res/layout/emoji_list.xml +++ b/app/src/main/res/layout/emoji_list.xml @@ -1,5 +1,5 @@ + + + + + + + + + + + + + + + + + + + + + + - - - - + app:layout_constraintTop_toBottomOf="@id/emoji_search_toolbar"> - - + android:layout_above="@id/emoji_palette_bottom_bar"> - + app:layout_constraintTop_toTopOf="@+id/mainToolbarKeyboardHolder"> بدء الجمل بحرف كبير الرموز التعبيرية + Search Emoji - \ No newline at end of file + diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index 0a4c7f181..fbcf11e23 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -38,6 +38,7 @@ Start sentences with a capital letter Эмодзі + Search Emoji Емоджита + Search Emoji Emojis + Search Emoji - \ No newline at end of file + diff --git a/app/src/main/res/values-ckb/strings.xml b/app/src/main/res/values-ckb/strings.xml index ecafe05fc..eccb2bb77 100644 --- a/app/src/main/res/values-ckb/strings.xml +++ b/app/src/main/res/values-ckb/strings.xml @@ -38,4 +38,5 @@ گەورەکردنی یەکەم پیتی لاتینی خەندەکان - \ No newline at end of file + Search Emoji + diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 0a89ba59b..2a3dc99b4 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -38,6 +38,7 @@ Začínat věty velkým písmenem Emotikony + Search Emoji Emojis + Search Emoji Emojis + Search Emoji - \ No newline at end of file + diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 867189bcb..d3d29b45d 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -38,6 +38,7 @@ Αρχίστε τις προτάσεις με κεφαλαίο γράμμα Emojis + Search Emoji Emojis + Search Emoji Emoticonos + Search Emoji - \ No newline at end of file + diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml index 3d3949b94..77884aad1 100644 --- a/app/src/main/res/values-et/strings.xml +++ b/app/src/main/res/values-et/strings.xml @@ -38,8 +38,9 @@ Alusta lauseid suurtähega Emojid + Search Emoji - \ No newline at end of file + diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 58f89baff..331908f51 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -38,6 +38,7 @@ Start sentences with a capital letter Emojit + Search Emoji Émojis + Search Emoji - \ No newline at end of file + diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index 659fc24f0..1b5cab40a 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -38,6 +38,7 @@ Start sentences with a capital letter Emoticona + Search Emoji Emoji + Search Emoji Emojik + Search Emoji Emoji + Search Emoji - \ No newline at end of file + diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 0a493097f..7e8135010 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -38,8 +38,9 @@ Inizia le frasi con la lettera maiuscola Emoji + Search Emoji - \ No newline at end of file + diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index 1a5bbadf3..0436e58a6 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -38,6 +38,7 @@ Start sentences with a capital letter Emojis + Search Emoji 絵文字 + Search Emoji Emojis + Search Emoji Emojis + Search Emoji Emocijzīmes + Search Emoji ഇമോജികൾ + Search Emoji diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index ee13235f5..b08c2ada7 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -38,6 +38,7 @@ Start sentences with a capital letter Emojis + Search Emoji Emoji\'s + Search Emoji - \ No newline at end of file + diff --git a/app/src/main/res/values-pa-rPK/strings.xml b/app/src/main/res/values-pa-rPK/strings.xml index 3bf51be7b..3c411b20c 100644 --- a/app/src/main/res/values-pa-rPK/strings.xml +++ b/app/src/main/res/values-pa-rPK/strings.xml @@ -38,4 +38,5 @@ Start sentences with a capital letter ایموجیاں + Search Emoji diff --git a/app/src/main/res/values-pa/strings.xml b/app/src/main/res/values-pa/strings.xml index bc674854f..b8da7d7be 100644 --- a/app/src/main/res/values-pa/strings.xml +++ b/app/src/main/res/values-pa/strings.xml @@ -38,4 +38,5 @@ ਵਾਕ ਵੱਡੇ ਅੱਖਰ ਨਾਲ ਸ਼ੁਰੂ ਕਰੋ Emojis - \ No newline at end of file + Search Emoji + diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 697fc541d..81732be9a 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -38,8 +38,9 @@ Zaczynaj zdania wielką literą Emoji + Search Emoji - \ No newline at end of file + diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 232e07917..f491c6626 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -38,6 +38,7 @@ Start sentences with a capital letter Emojis + Search Emoji Emojis + Search Emoji - \ No newline at end of file + diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 7d761066f..b9f21ea98 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -38,6 +38,7 @@ Start sentences with a capital letter Emoticoane + Search Emoji Эмодзи + Search Emoji Emoji + Search Emoji Emoji-ji + Search Emoji diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index c2d89ed8e..5b3371685 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -38,4 +38,5 @@ Start sentences with a capital letter Емоји + Search Emoji diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index fa7cca924..6b306bef8 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -38,6 +38,7 @@ Börja meningar med stor bokstav Emojier + Search Emoji Emojis + Search Emoji Emojiler + Search Emoji - \ No newline at end of file + diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 9a0d9c386..740bd0e97 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -38,6 +38,7 @@ Починати речення з великої літери Емодзі + Search Emoji Biểu tượng cảm xúc + Search Emoji 表情符号 + Search Emoji - \ No newline at end of file + diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index d099b1460..b0cc0c9b0 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -39,6 +39,7 @@ Start sentences with a capital letter Emojis + Search Emoji Emojis + Search Emoji + + + diff --git a/emojipicker/app/src/main/androidx/androidx/emoji2/androidx-emoji2-emoji2-emojipicker-documentation.md b/emojipicker/app/src/main/androidx/androidx/emoji2/androidx-emoji2-emoji2-emojipicker-documentation.md new file mode 100644 index 000000000..f751ab7bb --- /dev/null +++ b/emojipicker/app/src/main/androidx/androidx/emoji2/androidx-emoji2-emoji2-emojipicker-documentation.md @@ -0,0 +1,8 @@ +# Module root + +androidx.emoji2 emoji2-emojipicker + +# Package androidx.emoji2.emojipicker + +This library provides the latest emoji support and emoji picker UI including +skin-tone variants and emoji compat support. diff --git a/emojipicker/app/src/main/androidx/emoji2/androidx-emoji2-emoji2-emojipicker-documentation.md b/emojipicker/app/src/main/androidx/emoji2/androidx-emoji2-emoji2-emojipicker-documentation.md new file mode 100644 index 000000000..fc1b9355e --- /dev/null +++ b/emojipicker/app/src/main/androidx/emoji2/androidx-emoji2-emoji2-emojipicker-documentation.md @@ -0,0 +1,8 @@ +# Module root + +androidx.emoji2 emoji2-emojipicker + +# package reeshabh.emojipicker + +This library provides the latest emoji support and emoji picker UI including +skin-tone variants and emoji compat support. diff --git a/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/BundledEmojiListLoader.kt b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/BundledEmojiListLoader.kt new file mode 100644 index 000000000..f884679f7 --- /dev/null +++ b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/BundledEmojiListLoader.kt @@ -0,0 +1,134 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.emoji2.emojipicker + +import android.content.Context +import android.content.res.TypedArray +import androidx.annotation.DrawableRes +import androidx.core.content.res.use +import androidx.emoji2.emojipicker.utils.FileCache +import androidx.emoji2.emojipicker.utils.UnicodeRenderableManager +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.coroutineScope + +/** + * A data loader that loads the following objects either from file based caches or from resources. + * + * categorizedEmojiData: a list that holds bundled emoji separated by category, filtered by + * renderability check. This is the data source for EmojiPickerView. + * + * emojiVariantsLookup: a map of emoji variants in bundled emoji, keyed by the base emoji. This + * allows faster variants lookup. + * + * primaryEmojiLookup: a map of base emoji to its variants in bundled emoji. This allows faster + * variants lookup. + */ +internal object BundledEmojiListLoader { + private var categorizedEmojiData: List? = null + private var emojiVariantsLookup: Map>? = null + + internal suspend fun load(context: Context) { + val categoryNames = context.resources.getStringArray(R.array.category_names) + val categoryHeaderIconIds = + context.resources.obtainTypedArray(R.array.emoji_categories_icons).use { typedArray -> + IntArray(typedArray.length()) { typedArray.getResourceId(it, 0) } + } + val resources = + if (UnicodeRenderableManager.isEmoji12Supported()) + R.array.emoji_by_category_raw_resources_gender_inclusive + else R.array.emoji_by_category_raw_resources + val emojiFileCache = FileCache.getInstance(context) + + categorizedEmojiData = + context.resources.obtainTypedArray(resources).use { ta -> + loadEmoji(ta, categoryHeaderIconIds, categoryNames, emojiFileCache, context) + } + emojiVariantsLookup = + categorizedEmojiData!! + .flatMap { it.emojiDataList } + .filter { it.variants.isNotEmpty() } + .flatMap { it.variants.map { variant -> EmojiViewItem(variant, it.variants) } } + .associate { it.emoji to it.variants } + .also { emojiVariantsLookup = it } + } + + internal fun getCategorizedEmojiData() = + categorizedEmojiData + ?: throw IllegalStateException("BundledEmojiListLoader.load is not called or complete") + + internal fun getEmojiVariantsLookup() = + emojiVariantsLookup + ?: throw IllegalStateException("BundledEmojiListLoader.load is not called or complete") + + private suspend fun loadEmoji( + ta: TypedArray, + @DrawableRes categoryHeaderIconIds: IntArray, + categoryNames: Array, + emojiFileCache: FileCache, + context: Context + ): List = coroutineScope { + (0 until ta.length()) + .map { + async { + emojiFileCache + .getOrPut(getCacheFileName(it)) { + loadSingleCategory(context, ta.getResourceId(it, 0)) + } + .let { data -> + EmojiDataCategory(categoryHeaderIconIds[it], categoryNames[it], data) + } + } + } + .awaitAll() + } + + private fun loadSingleCategory( + context: Context, + resId: Int, + ): List = + context.resources + .openRawResource(resId) + .bufferedReader() + .useLines { it.toList() } + .map { filterRenderableEmojis(it.split(",")) } + .filter { it.isNotEmpty() } + .map { EmojiViewItem(it.first(), it.drop(1)) } + + private fun getCacheFileName(categoryIndex: Int) = + StringBuilder() + .append("emoji.v1.") + .append(if (EmojiPickerView.emojiCompatLoaded) 1 else 0) + .append(".") + .append(categoryIndex) + .append(".") + .append(if (UnicodeRenderableManager.isEmoji12Supported()) 1 else 0) + .toString() + + /** + * To eliminate 'Tofu' (the fallback glyph when an emoji is not renderable), check the + * renderability of emojis and keep only when they are renderable on the current device. + */ + private fun filterRenderableEmojis(emojiList: List) = + emojiList.filter { UnicodeRenderableManager.isEmojiRenderable(it) }.toList() + + internal data class EmojiDataCategory( + @DrawableRes val headerIconId: Int, + val categoryName: String, + val emojiDataList: List + ) +} diff --git a/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/DefaultRecentEmojiProvider.kt b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/DefaultRecentEmojiProvider.kt new file mode 100644 index 000000000..95a805da2 --- /dev/null +++ b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/DefaultRecentEmojiProvider.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.emoji2.emojipicker + +import android.content.Context +import android.content.Context.MODE_PRIVATE + +/** + * Provides recently shared emoji. This is the default recent emoji list provider. Clients could + * specify the provider by their own. + */ +internal class DefaultRecentEmojiProvider(context: Context) : RecentEmojiProvider { + + companion object { + private const val PREF_KEY_RECENT_EMOJI = "pref_key_recent_emoji" + private const val RECENT_EMOJI_LIST_FILE_NAME = "androidx.emoji2.emojipicker.preferences" + private const val SPLIT_CHAR = "," + } + + private val sharedPreferences = + context.getSharedPreferences(RECENT_EMOJI_LIST_FILE_NAME, MODE_PRIVATE) + private val recentEmojiList: MutableList = + sharedPreferences.getString(PREF_KEY_RECENT_EMOJI, null)?.split(SPLIT_CHAR)?.toMutableList() + ?: mutableListOf() + + override suspend fun getRecentEmojiList(): List { + return recentEmojiList + } + + override fun recordSelection(emoji: String) { + recentEmojiList.remove(emoji) + recentEmojiList.add(0, emoji) + saveToPreferences() + } + + private fun saveToPreferences() { + sharedPreferences + .edit() + .putString(PREF_KEY_RECENT_EMOJI, recentEmojiList.joinToString(SPLIT_CHAR)) + .commit() + } +} diff --git a/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerBodyAdapter.kt b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerBodyAdapter.kt new file mode 100644 index 000000000..178add782 --- /dev/null +++ b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerBodyAdapter.kt @@ -0,0 +1,139 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.emoji2.emojipicker + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.ViewGroup.LayoutParams +import android.widget.TextView +import androidx.annotation.LayoutRes +import androidx.annotation.UiThread +import androidx.core.view.ViewCompat +import androidx.emoji2.emojipicker.Extensions.toItemType +import androidx.recyclerview.widget.RecyclerView.Adapter +import androidx.recyclerview.widget.RecyclerView.ViewHolder + +/** RecyclerView adapter for emoji body. */ +internal class EmojiPickerBodyAdapter( + private val context: Context, + private val emojiGridColumns: Int, + private val emojiGridRows: Float?, + private val stickyVariantProvider: StickyVariantProvider, + private val emojiPickerItemsProvider: () -> EmojiPickerItems, + private val onEmojiPickedListener: EmojiPickerBodyAdapter.(EmojiViewItem) -> Unit, +) : Adapter() { + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + private var emojiCellWidth: Int? = null + private var emojiCellHeight: Int? = null + + @UiThread + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + emojiCellWidth = emojiCellWidth ?: (getParentWidth(parent) / emojiGridColumns) + emojiCellHeight = + emojiCellHeight + ?: emojiGridRows?.let { getEmojiCellTotalHeight(parent) / it }?.toInt() + ?: emojiCellWidth + + return when (viewType.toItemType()) { + ItemType.CATEGORY_TITLE -> createSimpleHolder(R.layout.category_text_view, parent) + ItemType.PLACEHOLDER_TEXT -> + createSimpleHolder(R.layout.empty_category_text_view, parent) { + minimumHeight = emojiCellHeight!! + } + ItemType.EMOJI -> { + EmojiViewHolder( + context, + emojiCellWidth!!, + emojiCellHeight!!, + stickyVariantProvider, + onEmojiPickedListener = { emojiViewItem -> + onEmojiPickedListener(emojiViewItem) + }, + onEmojiPickedFromPopupListener = { emoji -> + val baseEmoji = BundledEmojiListLoader.getEmojiVariantsLookup()[emoji]!![0] + emojiPickerItemsProvider().forEachIndexed { index, itemViewData -> + if ( + itemViewData is EmojiViewData && + BundledEmojiListLoader.getEmojiVariantsLookup()[ + itemViewData.emoji] + ?.get(0) == baseEmoji && + itemViewData.updateToSticky + ) { + itemViewData.emoji = emoji + notifyItemChanged(index) + } + } + } + ) + } + } + } + + override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) { + val item = emojiPickerItemsProvider().getBodyItem(position) + when (getItemViewType(position).toItemType()) { + ItemType.CATEGORY_TITLE -> + ViewCompat.requireViewById(viewHolder.itemView, R.id.category_name).text = + (item as CategoryTitle).title + ItemType.PLACEHOLDER_TEXT -> + ViewCompat.requireViewById( + viewHolder.itemView, + R.id.emoji_picker_empty_category_view + ) + .text = (item as PlaceholderText).text + ItemType.EMOJI -> { + (viewHolder as EmojiViewHolder).bindEmoji((item as EmojiViewData).emoji) + } + } + } + + override fun getItemId(position: Int): Long = + emojiPickerItemsProvider().getBodyItem(position).hashCode().toLong() + + override fun getItemCount(): Int { + return emojiPickerItemsProvider().size + } + + override fun getItemViewType(position: Int): Int { + return emojiPickerItemsProvider().getBodyItem(position).viewType + } + + private fun getParentWidth(parent: ViewGroup): Int { + return parent.measuredWidth - parent.paddingLeft - parent.paddingRight + } + + private fun getEmojiCellTotalHeight(parent: ViewGroup) = + parent.measuredHeight - + context.resources.getDimensionPixelSize(R.dimen.emoji_picker_category_name_height) * 2 - + context.resources.getDimensionPixelSize(R.dimen.emoji_picker_category_name_padding_top) + + private fun createSimpleHolder( + @LayoutRes layoutId: Int, + parent: ViewGroup, + init: (View.() -> Unit)? = null, + ) = + object : + ViewHolder( + layoutInflater.inflate(layoutId, parent, /* attachToRoot= */ false).also { + it.layoutParams = + LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT) + init?.invoke(it) + } + ) {} +} diff --git a/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerConstants.kt b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerConstants.kt new file mode 100644 index 000000000..ba7a5cfc9 --- /dev/null +++ b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerConstants.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.emoji2.emojipicker + +/** A utility class to hold various constants used by the Emoji Picker library. */ +internal object EmojiPickerConstants { + + // The default number of body columns. + const val DEFAULT_BODY_COLUMNS = 9 + + // The default number of rows of recent items held. + const val DEFAULT_MAX_RECENT_ITEM_ROWS = 3 + + // The max pool size of the Emoji ItemType in RecyclerViewPool. + const val EMOJI_VIEW_POOL_SIZE = 100 + + const val ADD_VIEW_EXCEPTION_MESSAGE = "Adding views to the EmojiPickerView is unsupported" + + const val REMOVE_VIEW_EXCEPTION_MESSAGE = + "Removing views from the EmojiPickerView is unsupported" +} diff --git a/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerHeaderAdapter.kt b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerHeaderAdapter.kt new file mode 100644 index 000000000..d4c8fa088 --- /dev/null +++ b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerHeaderAdapter.kt @@ -0,0 +1,88 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.emoji2.emojipicker + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.accessibility.AccessibilityEvent +import android.widget.ImageView +import androidx.core.view.ViewCompat +import androidx.recyclerview.widget.RecyclerView.Adapter +import androidx.recyclerview.widget.RecyclerView.ViewHolder + +/** RecyclerView adapter for emoji header. */ +internal class EmojiPickerHeaderAdapter( + context: Context, + private val emojiPickerItems: EmojiPickerItems, + private val onHeaderIconClicked: (Int) -> Unit, +) : Adapter() { + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + + var selectedGroupIndex: Int = 0 + set(value) { + if (value == field) return + notifyItemChanged(field) + notifyItemChanged(value) + field = value + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + return object : + ViewHolder( + layoutInflater.inflate( + R.layout.header_icon_holder, + parent, + /* attachToRoot = */ false + ) + ) {} + } + + override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) { + val isItemSelected = i == selectedGroupIndex + val headerIcon = + ViewCompat.requireViewById( + viewHolder.itemView, + R.id.emoji_picker_header_icon + ) + .apply { + setImageDrawable(context.getDrawable(emojiPickerItems.getHeaderIconId(i))) + isSelected = isItemSelected + contentDescription = emojiPickerItems.getHeaderIconDescription(i) + } + viewHolder.itemView.setOnClickListener { + onHeaderIconClicked(i) + selectedGroupIndex = i + } + if (isItemSelected) { + headerIcon.post { + headerIcon.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER) + } + } + + ViewCompat.requireViewById(viewHolder.itemView, R.id.emoji_picker_header_underline) + .apply { + visibility = if (isItemSelected) View.VISIBLE else View.GONE + isSelected = isItemSelected + } + } + + override fun getItemCount(): Int { + return emojiPickerItems.numGroups + } +} diff --git a/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerItems.kt b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerItems.kt new file mode 100644 index 000000000..2d7b36dd4 --- /dev/null +++ b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerItems.kt @@ -0,0 +1,111 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.emoji2.emojipicker + +import androidx.annotation.DrawableRes +import androidx.annotation.IntRange + +/** + * A group of items in RecyclerView for emoji picker body. [titleItem] comes first. [contentItems] + * comes after [titleItem]. [emptyPlaceholderItem] will be served after [titleItem] only if + * [contentItems] is empty. [maxContentItemCount], if provided, will truncate [contentItems] to + * certain size. + * + * [categoryIconId] is the corresponding category icon in emoji picker header. + */ +internal class ItemGroup( + @DrawableRes internal val categoryIconId: Int, + internal val titleItem: CategoryTitle, + private val contentItems: List, + private val maxContentItemCount: Int? = null, + private val emptyPlaceholderItem: PlaceholderText? = null +) { + + val size: Int + get() = + 1 /* title */ + + when { + contentItems.isEmpty() -> if (emptyPlaceholderItem != null) 1 else 0 + maxContentItemCount != null && contentItems.size > maxContentItemCount -> + maxContentItemCount + else -> contentItems.size + } + + operator fun get(index: Int): ItemViewData { + if (index == 0) return titleItem + val contentIndex = index - 1 + if (contentIndex < contentItems.size) return contentItems[contentIndex] + if (contentIndex == 0 && emptyPlaceholderItem != null) return emptyPlaceholderItem + throw IndexOutOfBoundsException() + } + + fun getAll(): List = IntRange(0, size - 1).map { get(it) } +} + +/** A view of concatenated list of [ItemGroup]. */ +internal class EmojiPickerItems( + private val groups: List, +) : Iterable { + val size: Int + get() = groups.sumOf { it.size } + + init { + check(groups.isNotEmpty()) { "Initialized with empty categorized sources" } + } + + fun getBodyItem(@IntRange(from = 0) absolutePosition: Int): ItemViewData { + var localPosition = absolutePosition + for (group in groups) { + if (localPosition < group.size) return group[localPosition] + else localPosition -= group.size + } + throw IndexOutOfBoundsException() + } + + val numGroups: Int + get() = groups.size + + @DrawableRes + fun getHeaderIconId(@IntRange(from = 0) index: Int): Int = groups[index].categoryIconId + + fun getHeaderIconDescription(@IntRange(from = 0) index: Int): String = + groups[index].titleItem.title + + fun groupIndexByItemPosition(@IntRange(from = 0) absolutePosition: Int): Int { + var localPosition = absolutePosition + var index = 0 + for (group in groups) { + if (localPosition < group.size) return index + else { + localPosition -= group.size + index++ + } + } + throw IndexOutOfBoundsException() + } + + fun firstItemPositionByGroupIndex(@IntRange(from = 0) groupIndex: Int): Int = + groups.take(groupIndex).sumOf { it.size } + + fun groupRange(group: ItemGroup): kotlin.ranges.IntRange { + check(groups.contains(group)) + val index = groups.indexOf(group) + return firstItemPositionByGroupIndex(index).let { it until it + group.size } + } + + override fun iterator(): Iterator = groups.flatMap { it.getAll() }.iterator() +} diff --git a/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerPopupBidirectionalDesign.kt b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerPopupBidirectionalDesign.kt new file mode 100644 index 000000000..ffe773b01 --- /dev/null +++ b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerPopupBidirectionalDesign.kt @@ -0,0 +1,110 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.emoji2.emojipicker + +import android.content.Context +import android.view.Gravity +import android.view.View +import android.view.ViewGroup +import android.widget.FrameLayout +import android.widget.LinearLayout +import androidx.appcompat.widget.AppCompatImageView + +/** Emoji picker popup view with bidirectional UI design to switch emoji to face left or right. */ +internal class EmojiPickerPopupBidirectionalDesign( + override val context: Context, + override val targetEmojiView: View, + override val variants: List, + override val popupView: LinearLayout, + override val emojiViewOnClickListener: View.OnClickListener +) : EmojiPickerPopupDesign() { + private var emojiFacingLeft = true + + init { + updateTemplate() + } + + override fun addLayoutHeader() { + val row = + LinearLayout(context).apply { + orientation = LinearLayout.HORIZONTAL + gravity = Gravity.CENTER + layoutParams = + LinearLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + } + FrameLayout.inflate(context, R.layout.emoji_picker_popup_bidirectional, row) + .findViewById(R.id.emoji_picker_popup_bidirectional_icon) + .apply { + layoutParams = + LinearLayout.LayoutParams(targetEmojiView.width, targetEmojiView.height) + } + popupView.addView(row) + val imageView = + row.findViewById(R.id.emoji_picker_popup_bidirectional_icon) + imageView.setOnClickListener { + emojiFacingLeft = !emojiFacingLeft + updateTemplate() + popupView.removeViews(/* start= */ 1, getActualNumberOfRows()) + addRowsToPopupView() + imageView.announceForAccessibility( + context.getString(R.string.emoji_bidirectional_switcher_clicked_desc) + ) + } + } + + override fun getNumberOfRows(): Int { + // Adding one row for the bidirectional switcher. + return variants.size / 2 / BIDIRECTIONAL_COLUMN_COUNT + 1 + } + + override fun getNumberOfColumns(): Int { + return BIDIRECTIONAL_COLUMN_COUNT + } + + private fun getActualNumberOfRows(): Int { + // Removing one extra row of the bidirectional switcher. + return getNumberOfRows() - 1 + } + + private fun updateTemplate() { + template = + if (emojiFacingLeft) + arrayOf((variants.indices.filter { it % 12 < 6 }.map { it + 1 }).toIntArray()) + else arrayOf((variants.indices.filter { it % 12 >= 6 }.map { it + 1 }).toIntArray()) + + val row = getActualNumberOfRows() + val column = getNumberOfColumns() + val overrideTemplate = Array(row) { IntArray(column) } + var index = 0 + for (i in 0 until row) { + for (j in 0 until column) { + if (index < template[0].size) { + overrideTemplate[i][j] = template[0][index] + index++ + } + } + } + template = overrideTemplate + } + + companion object { + private const val BIDIRECTIONAL_COLUMN_COUNT = 6 + } +} diff --git a/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerPopupDesign.kt b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerPopupDesign.kt new file mode 100644 index 000000000..6111539da --- /dev/null +++ b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerPopupDesign.kt @@ -0,0 +1,89 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.emoji2.emojipicker + +import android.content.Context +import android.view.View +import android.view.ViewGroup +import android.view.accessibility.AccessibilityEvent +import android.widget.FrameLayout +import android.widget.LinearLayout + +/** Emoji picker popup view UI design. Each UI design needs to inherit this abstract class. */ +internal abstract class EmojiPickerPopupDesign { + abstract val context: Context + abstract val targetEmojiView: View + abstract val variants: List + abstract val popupView: LinearLayout + abstract val emojiViewOnClickListener: View.OnClickListener + lateinit var template: Array + + open fun addLayoutHeader() { + // no-ops + } + + open fun addRowsToPopupView() { + for (row in template) { + val rowLayout = + LinearLayout(context).apply { + orientation = LinearLayout.HORIZONTAL + layoutParams = + LinearLayout.LayoutParams( + FrameLayout.LayoutParams.WRAP_CONTENT, + FrameLayout.LayoutParams.WRAP_CONTENT + ) + } + for (item in row) { + val cell = + if (item == 0) { + EmojiView(context) + } else { + EmojiView(context).apply { + willDrawVariantIndicator = false + emoji = variants[item - 1] + setOnClickListener(emojiViewOnClickListener) + if (item == 1) { + // Hover on the first emoji in the popup + popupView.post { + sendAccessibilityEvent( + AccessibilityEvent.TYPE_VIEW_HOVER_ENTER + ) + } + } + } + } + .apply { + layoutParams = + ViewGroup.LayoutParams( + targetEmojiView.width, + targetEmojiView.height + ) + } + rowLayout.addView(cell) + } + popupView.addView(rowLayout) + } + } + + open fun addLayoutFooter() { + // no-ops + } + + abstract fun getNumberOfRows(): Int + + abstract fun getNumberOfColumns(): Int +} diff --git a/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerPopupFlatDesign.kt b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerPopupFlatDesign.kt new file mode 100644 index 000000000..813a1ea92 --- /dev/null +++ b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerPopupFlatDesign.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.emoji2.emojipicker + +import android.content.Context +import android.view.View +import android.widget.LinearLayout + +/** Emoji picker popup view with flat design to list emojis. */ +internal class EmojiPickerPopupFlatDesign( + override val context: Context, + override val targetEmojiView: View, + override val variants: List, + override val popupView: LinearLayout, + override val emojiViewOnClickListener: View.OnClickListener +) : EmojiPickerPopupDesign() { + init { + template = arrayOf(variants.indices.map { it + 1 }.toIntArray()) + var row = getNumberOfRows() + var column = getNumberOfColumns() + val overrideTemplate = Array(row) { IntArray(column) } + var index = 0 + for (i in 0 until row) { + for (j in 0 until column) { + if (index < template[0].size) { + overrideTemplate[i][j] = template[0][index] + index++ + } + } + } + template = overrideTemplate + } + + override fun getNumberOfRows(): Int { + val column = getNumberOfColumns() + return variants.size / column + if (variants.size % column == 0) 0 else 1 + } + + override fun getNumberOfColumns(): Int { + return minOf(FLAT_COLUMN_MAX_COUNT, template[0].size) + } + + companion object { + private const val FLAT_COLUMN_MAX_COUNT = 6 + } +} diff --git a/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerPopupMultiSkintoneDesign.kt b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerPopupMultiSkintoneDesign.kt new file mode 100644 index 000000000..949a75edb --- /dev/null +++ b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerPopupMultiSkintoneDesign.kt @@ -0,0 +1,400 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.emoji2.emojipicker + +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.Color +import android.graphics.drawable.Drawable +import android.util.Log +import android.view.ContextThemeWrapper +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.FrameLayout +import android.widget.ImageView +import android.widget.LinearLayout +import androidx.annotation.StringRes +import androidx.core.content.res.ResourcesCompat +import com.google.common.collect.ImmutableMap +import com.google.common.primitives.ImmutableIntArray + +/** Emoji picker popup with multi-skintone selection panel. */ +internal class EmojiPickerPopupMultiSkintoneDesign( + override val context: Context, + override val targetEmojiView: View, + override val variants: List, + override val popupView: LinearLayout, + override val emojiViewOnClickListener: View.OnClickListener, + targetEmoji: String +) : EmojiPickerPopupDesign() { + + private val inflater = LayoutInflater.from(context) + private val resultRow = + LinearLayout(context).apply { + orientation = LinearLayout.HORIZONTAL + layoutParams = + LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + } + + private var selectedLeftSkintone = -1 + private var selectedRightSkintone = -1 + + init { + val triggerVariantIndex: Int = variants.indexOf(targetEmoji) + if (triggerVariantIndex > 0) { + selectedLeftSkintone = (triggerVariantIndex - 1) / getNumberOfColumns() + selectedRightSkintone = + triggerVariantIndex - selectedLeftSkintone * getNumberOfColumns() - 1 + } + } + + override fun addRowsToPopupView() { + for (row in 0 until getActualNumberOfRows()) { + val rowLayout = + LinearLayout(context).apply { + orientation = LinearLayout.HORIZONTAL + layoutParams = + LinearLayout.LayoutParams( + FrameLayout.LayoutParams.WRAP_CONTENT, + FrameLayout.LayoutParams.WRAP_CONTENT + ) + } + for (column in 0 until getNumberOfColumns()) { + inflater.inflate(R.layout.emoji_picker_popup_image_view, rowLayout) + val imageView = rowLayout.getChildAt(column) as ImageView + imageView.apply { + layoutParams = + LinearLayout.LayoutParams(targetEmojiView.width, targetEmojiView.height) + isClickable = true + contentDescription = getImageContentDescription(context, row, column) + if ( + (hasLeftSkintone() && row == 0 && selectedLeftSkintone == column) || + (hasRightSkintone() && row == 1 && selectedRightSkintone == column) + ) { + isSelected = true + isClickable = false + } + setImageDrawable(getDrawableRes(context, row, column)) + setOnClickListener { + var unSelectedView: View? = null + if (row == 0) { + if (hasLeftSkintone()) { + unSelectedView = rowLayout.getChildAt(selectedLeftSkintone) + } + selectedLeftSkintone = column + } else { + if (hasRightSkintone()) { + unSelectedView = rowLayout.getChildAt(selectedRightSkintone) + } + selectedRightSkintone = column + } + if (unSelectedView != null) { + unSelectedView.isSelected = false + unSelectedView.isClickable = true + } + isClickable = false + isSelected = true + processResultView() + } + } + } + popupView.addView(rowLayout) + } + } + + private fun processResultView() { + val childCount = resultRow.childCount + if (childCount < 1 || childCount > 2) { + Log.e(TAG, "processResultEmojiForRectangleLayout(): unexpected emoji result row size") + return + } + // Remove the result emoji if it's already available. It will be available after the row is + // inflated the first time. + if (childCount == 2) { + resultRow.removeViewAt(1) + } + if (hasLeftSkintone() && hasRightSkintone()) { + inflater.inflate(R.layout.emoji_picker_popup_emoji_view, resultRow) + val layout = resultRow.getChildAt(1) as LinearLayout + layout.findViewById(R.id.emoji_picker_popup_emoji_view).apply { + willDrawVariantIndicator = false + isClickable = true + emoji = + variants[ + selectedLeftSkintone * getNumberOfColumns() + selectedRightSkintone + 1] + setOnClickListener(emojiViewOnClickListener) + layoutParams = + LinearLayout.LayoutParams(targetEmojiView.width, targetEmojiView.height) + } + layout.findViewById(R.id.emoji_picker_popup_emoji_view_wrapper).apply { + layoutParams = + LinearLayout.LayoutParams( + targetEmojiView.width * getNumberOfColumns() / 2, + targetEmojiView.height + ) + } + } else if (hasLeftSkintone()) { + drawImageView( + /* row= */ 0, + /*column=*/ selectedLeftSkintone, + /* applyGrayTint= */ false + ) + } else if (hasRightSkintone()) { + drawImageView( + /* row= */ 1, + /*column=*/ selectedRightSkintone, + /* applyGrayTint= */ false + ) + } else { + drawImageView(/* row= */ 0, /* column= */ 0, /* applyGrayTint= */ true) + } + } + + private fun drawImageView(row: Int, column: Int, applyGrayTint: Boolean) { + inflater + .inflate(R.layout.emoji_picker_popup_image_view, resultRow) + .findViewById(R.id.emoji_picker_popup_image_view) + .apply { + layoutParams = LinearLayout.LayoutParams(0, targetEmojiView.height, 1f) + setImageDrawable(getDrawableRes(context, row, column)) + if (applyGrayTint) { + imageTintList = ColorStateList.valueOf(Color.GRAY) + } + + var contentDescriptionRow = selectedLeftSkintone + var contentDescriptionColumn = selectedRightSkintone + if (hasLeftSkintone()) { + contentDescriptionRow = 0 + contentDescriptionColumn = selectedLeftSkintone + } else if (hasRightSkintone()) { + contentDescriptionRow = 1 + contentDescriptionColumn = selectedRightSkintone + } + contentDescription = + getImageContentDescription( + context, + contentDescriptionRow, + contentDescriptionColumn + ) + } + } + + override fun addLayoutFooter() { + inflater.inflate(R.layout.emoji_picker_popup_emoji_view, resultRow) + val layout = resultRow.getChildAt(0) as LinearLayout + layout.findViewById(R.id.emoji_picker_popup_emoji_view).apply { + willDrawVariantIndicator = false + emoji = variants[0] + layoutParams = LinearLayout.LayoutParams(targetEmojiView.width, targetEmojiView.height) + isClickable = true + setOnClickListener(emojiViewOnClickListener) + } + layout.findViewById(R.id.emoji_picker_popup_emoji_view_wrapper).apply { + layoutParams = + LinearLayout.LayoutParams( + targetEmojiView.width * getNumberOfColumns() / 2, + targetEmojiView.height + ) + } + processResultView() + popupView.addView(resultRow) + } + + override fun getNumberOfRows(): Int { + // Add one extra row for the neutral skin tone combination + return LAYOUT_ROWS + 1 + } + + override fun getNumberOfColumns(): Int { + return LAYOUT_COLUMNS + } + + private fun getActualNumberOfRows(): Int { + return LAYOUT_ROWS + } + + private fun hasLeftSkintone(): Boolean { + return selectedLeftSkintone != -1 + } + + private fun hasRightSkintone(): Boolean { + return selectedRightSkintone != -1 + } + + private fun getDrawableRes(context: Context, row: Int, column: Int): Drawable? { + val resArray: ImmutableIntArray? = SKIN_TONES_EMOJI_TO_RESOURCES[variants[0]] + if (resArray != null) { + val contextThemeWrapper = ContextThemeWrapper(context, VARIANT_STYLES[column]) + return ResourcesCompat.getDrawable( + context.resources, + resArray[row], + contextThemeWrapper.getTheme() + ) + } + return null + } + + private fun getImageContentDescription(context: Context, row: Int, column: Int): String { + return context.getString( + R.string.emoji_variant_content_desc_template, + context.getString(getSkintoneStringRes(/* isLeft= */ true, row, column)), + context.getString(getSkintoneStringRes(/* isLeft= */ false, row, column)) + ) + } + + @StringRes + private fun getSkintoneStringRes(isLeft: Boolean, row: Int, column: Int): Int { + // When there is no column, the selected position -1 will be passed in as column. + if (column == -1) { + return R.string.emoji_skin_tone_shadow_content_desc + } + return if (isLeft) { + if (row == 0) SKIN_TONE_CONTENT_DESC_RES_IDS[column] + else R.string.emoji_skin_tone_shadow_content_desc + } else { + if (row == 0) R.string.emoji_skin_tone_shadow_content_desc + else SKIN_TONE_CONTENT_DESC_RES_IDS[column] + } + } + + companion object { + private const val TAG = "MultiSkintoneDesign" + private const val LAYOUT_ROWS = 2 + private const val LAYOUT_COLUMNS = 5 + + private val SKIN_TONE_CONTENT_DESC_RES_IDS = + ImmutableIntArray.of( + R.string.emoji_skin_tone_light_content_desc, + R.string.emoji_skin_tone_medium_light_content_desc, + R.string.emoji_skin_tone_medium_content_desc, + R.string.emoji_skin_tone_medium_dark_content_desc, + R.string.emoji_skin_tone_dark_content_desc + ) + + private val VARIANT_STYLES = + ImmutableIntArray.of( + R.style.EmojiSkintoneSelectorLight, + R.style.EmojiSkintoneSelectorMediumLight, + R.style.EmojiSkintoneSelectorMedium, + R.style.EmojiSkintoneSelectorMediumDark, + R.style.EmojiSkintoneSelectorDark + ) + + /** + * Map from emoji that use the square layout strategy with skin tone swatches or rectangle + * strategy to their resources. + */ + private val SKIN_TONES_EMOJI_TO_RESOURCES = + ImmutableMap.Builder() + .put( + "🤝", + ImmutableIntArray.of( + R.drawable.handshake_skintone_shadow, + R.drawable.handshake_shadow_skintone + ) + ) + .put( + "👭", + ImmutableIntArray.of( + R.drawable.holding_women_skintone_shadow, + R.drawable.holding_women_shadow_skintone + ) + ) + .put( + "👫", + ImmutableIntArray.of( + R.drawable.holding_woman_man_skintone_shadow, + R.drawable.holding_woman_man_shadow_skintone + ) + ) + .put( + "👬", + ImmutableIntArray.of( + R.drawable.holding_men_skintone_shadow, + R.drawable.holding_men_shadow_skintone + ) + ) + .put( + "🧑‍🤝‍🧑", + ImmutableIntArray.of( + R.drawable.holding_people_skintone_shadow, + R.drawable.holding_people_shadow_skintone + ) + ) + .put( + "💏", + ImmutableIntArray.of( + R.drawable.kiss_people_skintone_shadow, + R.drawable.kiss_people_shadow_skintone + ) + ) + .put( + "👩‍❤️‍💋‍👨", + ImmutableIntArray.of( + R.drawable.kiss_woman_man_skintone_shadow, + R.drawable.kiss_woman_man_shadow_skintone + ) + ) + .put( + "👨‍❤️‍💋‍👨", + ImmutableIntArray.of( + R.drawable.kiss_men_skintone_shadow, + R.drawable.kiss_men_shadow_skintone + ) + ) + .put( + "👩‍❤️‍💋‍👩", + ImmutableIntArray.of( + R.drawable.kiss_women_skintone_shadow, + R.drawable.kiss_women_shadow_skintone + ) + ) + .put( + "💑", + ImmutableIntArray.of( + R.drawable.couple_heart_people_skintone_shadow, + R.drawable.couple_heart_people_shadow_skintone + ) + ) + .put( + "👩‍❤️‍👨", + ImmutableIntArray.of( + R.drawable.couple_heart_woman_man_skintone_shadow, + R.drawable.couple_heart_woman_man_shadow_skintone + ) + ) + .put( + "👨‍❤️‍👨", + ImmutableIntArray.of( + R.drawable.couple_heart_men_skintone_shadow, + R.drawable.couple_heart_men_shadow_skintone + ) + ) + .put( + "👩‍❤️‍👩", + ImmutableIntArray.of( + R.drawable.couple_heart_women_skintone_shadow, + R.drawable.couple_heart_women_shadow_skintone + ) + ) + .buildOrThrow() + } +} diff --git a/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerPopupSquareDesign.kt b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerPopupSquareDesign.kt new file mode 100644 index 000000000..13f94c6c6 --- /dev/null +++ b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerPopupSquareDesign.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.emoji2.emojipicker + +import android.content.Context +import android.view.View +import android.widget.LinearLayout + +/** Emoji picker popup view with square design. */ +internal class EmojiPickerPopupSquareDesign( + override val context: Context, + override val targetEmojiView: View, + override val variants: List, + override val popupView: LinearLayout, + override val emojiViewOnClickListener: View.OnClickListener +) : EmojiPickerPopupDesign() { + init { + template = SQUARE_LAYOUT_TEMPLATE + } + + override fun getNumberOfRows(): Int { + return SQUARE_LAYOUT_TEMPLATE.size + } + + override fun getNumberOfColumns(): Int { + return SQUARE_LAYOUT_TEMPLATE[0].size + } + + companion object { + /** + * Square variant layout template without skin tone. 0 : a place holder Positive number is + * the index + 1 in the variant array + */ + private val SQUARE_LAYOUT_TEMPLATE = + arrayOf( + intArrayOf(0, 2, 3, 4, 5, 6), + intArrayOf(0, 7, 8, 9, 10, 11), + intArrayOf(0, 12, 13, 14, 15, 16), + intArrayOf(0, 17, 18, 19, 20, 21), + intArrayOf(1, 22, 23, 24, 25, 26) + ) + } +} diff --git a/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerPopupView.kt b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerPopupView.kt new file mode 100644 index 000000000..fcb2aabe0 --- /dev/null +++ b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerPopupView.kt @@ -0,0 +1,134 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.emoji2.emojipicker + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import android.widget.FrameLayout +import android.widget.LinearLayout + +/** Popup view for emoji picker to show emoji variants. */ +internal class EmojiPickerPopupView +@JvmOverloads +constructor( + context: Context, + attrs: AttributeSet?, + defStyleAttr: Int = 0, + private val targetEmojiView: View, + private val targetEmojiItem: EmojiViewItem, + private val emojiViewOnClickListener: OnClickListener +) : FrameLayout(context, attrs, defStyleAttr) { + + private val variants = targetEmojiItem.variants + private val targetEmoji = targetEmojiItem.emoji + private val popupView: LinearLayout + private val popupDesign: EmojiPickerPopupDesign + + init { + popupView = + inflate(context, R.layout.variant_popup, /* root= */ null) + .findViewById(R.id.variant_popup) + val layout = getLayout() + popupDesign = + when (layout) { + Layout.FLAT -> + EmojiPickerPopupFlatDesign( + context, + targetEmojiView, + variants, + popupView, + emojiViewOnClickListener + ) + Layout.SQUARE -> + EmojiPickerPopupSquareDesign( + context, + targetEmojiView, + variants, + popupView, + emojiViewOnClickListener + ) + Layout.SQUARE_WITH_SKIN_TONE_CIRCLE -> + EmojiPickerPopupMultiSkintoneDesign( + context, + targetEmojiView, + variants, + popupView, + emojiViewOnClickListener, + targetEmoji + ) + Layout.BIDIRECTIONAL -> + EmojiPickerPopupBidirectionalDesign( + context, + targetEmojiView, + variants, + popupView, + emojiViewOnClickListener + ) + } + popupDesign.addLayoutHeader() + popupDesign.addRowsToPopupView() + popupDesign.addLayoutFooter() + addView(popupView) + } + + fun getPopupViewWidth(): Int { + return popupDesign.getNumberOfColumns() * targetEmojiView.width + + popupView.paddingStart + + popupView.paddingEnd + } + + fun getPopupViewHeight(): Int { + return popupDesign.getNumberOfRows() * targetEmojiView.height + + popupView.paddingTop + + popupView.paddingBottom + } + + private fun getLayout(): Layout { + if (variants.size == SQUARE_LAYOUT_VARIANT_COUNT) + if (SQUARE_LAYOUT_EMOJI_NO_SKIN_TONE.contains(variants[0])) return Layout.SQUARE + else return Layout.SQUARE_WITH_SKIN_TONE_CIRCLE + else if (variants.size == BIDIRECTIONAL_VARIANTS_COUNT) return Layout.BIDIRECTIONAL + else return Layout.FLAT + } + + companion object { + private enum class Layout { + FLAT, + SQUARE, + SQUARE_WITH_SKIN_TONE_CIRCLE, + BIDIRECTIONAL + } + + /** + * The number of variants expected when using a square layout strategy. Square layouts are + * comprised of a 5x5 grid + the base variant. + */ + private const val SQUARE_LAYOUT_VARIANT_COUNT = 26 + + /** + * The number of variants expected when using a bidirectional layout strategy. Bidirectional + * layouts are comprised of bidirectional icon and a 3x6 grid with left direction emojis as + * default. After clicking the bidirectional icon, it switches to a bidirectional icon and a + * 3x6 grid with right direction emojis. + */ + private const val BIDIRECTIONAL_VARIANTS_COUNT = 36 + + // Set of emojis that use the square layout without skin tone swatches. + private val SQUARE_LAYOUT_EMOJI_NO_SKIN_TONE = setOf("👪") + } +} diff --git a/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerPopupViewController.kt b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerPopupViewController.kt new file mode 100644 index 000000000..479cf7417 --- /dev/null +++ b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerPopupViewController.kt @@ -0,0 +1,84 @@ +package androidx.emoji2.emojipicker + +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import android.content.Context +import android.view.Gravity +import android.view.View +import android.view.ViewGroup.LayoutParams +import android.view.WindowManager +import android.widget.PopupWindow +import android.widget.Toast +import kotlin.math.roundToInt + +/** + * Default controller class for emoji picker popup view. + * + *

Shows the popup view above the target Emoji. View under control is a {@code + * EmojiPickerPopupView}. + */ +internal class EmojiPickerPopupViewController( + private val context: Context, + private val emojiPickerPopupView: EmojiPickerPopupView, + private val clickedEmojiView: View +) { + private val popupWindow: PopupWindow = + PopupWindow( + emojiPickerPopupView, + LayoutParams.WRAP_CONTENT, + LayoutParams.WRAP_CONTENT, + /* focusable= */ false + ) + + fun show() { + popupWindow.apply { + val location = IntArray(2) + clickedEmojiView.getLocationInWindow(location) + // Make the popup view center align with the target emoji view. + val x = + location[0] + clickedEmojiView.width / 2f - + emojiPickerPopupView.getPopupViewWidth() / 2f + val y = location[1] - emojiPickerPopupView.getPopupViewHeight() + // Set background drawable so that the popup window is dismissed properly when clicking + // outside / scrolling for API < 23. + setBackgroundDrawable(context.getDrawable(R.drawable.popup_view_rounded_background)) + isOutsideTouchable = true + isTouchable = true + animationStyle = R.style.VariantPopupAnimation + elevation = + clickedEmojiView.context.resources + .getDimensionPixelSize(R.dimen.emoji_picker_popup_view_elevation) + .toFloat() + try { + showAtLocation(clickedEmojiView, Gravity.NO_GRAVITY, x.roundToInt(), y) + } catch (e: WindowManager.BadTokenException) { + Toast.makeText( + context, + "Don't use EmojiPickerView inside a Popup", + Toast.LENGTH_LONG + ) + .show() + } + } + } + + fun dismiss() { + if (popupWindow.isShowing) { + popupWindow.dismiss() + } + } +} diff --git a/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerView.kt b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerView.kt new file mode 100644 index 000000000..b6be0514c --- /dev/null +++ b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiPickerView.kt @@ -0,0 +1,460 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.emoji2.emojipicker + +import android.content.Context +import android.content.res.TypedArray +import android.util.AttributeSet +import android.view.View +import android.view.ViewGroup +import android.widget.FrameLayout +import androidx.core.util.Consumer +import androidx.core.view.ViewCompat +import androidx.emoji2.emojipicker.EmojiPickerConstants.DEFAULT_MAX_RECENT_ITEM_ROWS +import androidx.emoji2.text.EmojiCompat +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import kotlin.coroutines.EmptyCoroutineContext +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext + +/** + * The emoji picker view that provides up-to-date emojis in a vertical scrollable view with a + * clickable horizontal header. + */ +class EmojiPickerView +@JvmOverloads +constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : + FrameLayout(context, attrs, defStyleAttr) { + + internal companion object { + internal var emojiCompatLoaded: Boolean = false + } + + private var _emojiGridRows: Float? = null + /** + * The number of rows of the emoji picker. + * + * Optional field. If not set, the value will be calculated based on parent view height and + * [emojiGridColumns]. Float value indicates that the picker could display the last row + * partially, so the users get the idea that they can scroll down for more contents. + * + * @attr ref androidx.emoji2.emojipicker.R.styleable.EmojiPickerView_emojiGridRows + */ + var emojiGridRows: Float + get() = _emojiGridRows ?: -1F + set(value) { + _emojiGridRows = value.takeIf { it > 0 } + // Refresh when emojiGridRows is reset + if (isLaidOut) { + showEmojiPickerView() + } + } + + /** + * The number of columns of the emoji picker. + * + * Default value([EmojiPickerConstants.DEFAULT_BODY_COLUMNS]: 9) will be used if + * emojiGridColumns is set to non-positive value. + * + * @attr ref androidx.emoji2.emojipicker.R.styleable.EmojiPickerView_emojiGridColumns + */ + var emojiGridColumns: Int = EmojiPickerConstants.DEFAULT_BODY_COLUMNS + set(value) { + field = value.takeIf { it > 0 } ?: EmojiPickerConstants.DEFAULT_BODY_COLUMNS + // Refresh when emojiGridColumns is reset + if (isLaidOut) { + showEmojiPickerView() + } + } + + private val stickyVariantProvider = StickyVariantProvider(context) + private val scope = CoroutineScope(EmptyCoroutineContext) + + private var recentEmojiProvider: RecentEmojiProvider = DefaultRecentEmojiProvider(context) + private var recentNeedsRefreshing: Boolean = true + private val recentItems: MutableList = mutableListOf() + private lateinit var recentItemGroup: ItemGroup + + private lateinit var emojiPickerItems: EmojiPickerItems + private lateinit var bodyAdapter: EmojiPickerBodyAdapter + + private var onEmojiPickedListener: Consumer? = null + + init { + + val typedArray: TypedArray = + context.obtainStyledAttributes(attrs, R.styleable.EmojiPickerView, 0, 0) + _emojiGridRows = + with(R.styleable.EmojiPickerView_emojiGridRows) { + if (typedArray.hasValue(this)) { + typedArray.getFloat(this, 0F) + } else null + } + emojiGridColumns = + typedArray.getInt( + R.styleable.EmojiPickerView_emojiGridColumns, + EmojiPickerConstants.DEFAULT_BODY_COLUMNS + ) + typedArray.recycle() + + if (EmojiCompat.isConfigured()) { + when (EmojiCompat.get().loadState) { + EmojiCompat.LOAD_STATE_SUCCEEDED -> emojiCompatLoaded = true + EmojiCompat.LOAD_STATE_LOADING, + EmojiCompat.LOAD_STATE_DEFAULT -> + EmojiCompat.get() + .registerInitCallback( + object : EmojiCompat.InitCallback() { + override fun onInitialized() { + emojiCompatLoaded = true + scope.launch(Dispatchers.IO) { + BundledEmojiListLoader.load(context) + withContext(Dispatchers.Main) { + emojiPickerItems = buildEmojiPickerItems() + bodyAdapter.notifyDataSetChanged() + } + } + } + + override fun onFailed(throwable: Throwable?) {} + } + ) + } + } + scope.launch(Dispatchers.IO) { + val load = launch { BundledEmojiListLoader.load(context) } + refreshRecent() + load.join() + + withContext(Dispatchers.Main) { showEmojiPickerView() } + } + } + + private fun createEmojiPickerBodyAdapter(): EmojiPickerBodyAdapter { + return EmojiPickerBodyAdapter( + context, + emojiGridColumns, + _emojiGridRows, + stickyVariantProvider, + emojiPickerItemsProvider = { emojiPickerItems }, + onEmojiPickedListener = { emojiViewItem -> + onEmojiPickedListener?.accept(emojiViewItem) + recentEmojiProvider.recordSelection(emojiViewItem.emoji) + recentNeedsRefreshing = true + } + ) + } + + internal fun buildEmojiPickerItems() = + EmojiPickerItems( + buildList { + add( + ItemGroup( + R.drawable.quantum_gm_ic_access_time_filled_vd_theme_24, + CategoryTitle(context.getString(R.string.emoji_category_recent)), + recentItems, + maxContentItemCount = DEFAULT_MAX_RECENT_ITEM_ROWS * emojiGridColumns, + emptyPlaceholderItem = + PlaceholderText( + context.getString(R.string.emoji_empty_recent_category) + ) + ) + .also { recentItemGroup = it } + ) + + for ((i, category) in + BundledEmojiListLoader.getCategorizedEmojiData().withIndex()) { + add( + ItemGroup( + category.headerIconId, + CategoryTitle(category.categoryName), + category.emojiDataList.mapIndexed { j, emojiData -> + EmojiViewData( + stickyVariantProvider[emojiData.emoji], + dataIndex = i + j + ) + }, + ) + ) + } + } + ) + + private fun showEmojiPickerView() { + emojiPickerItems = buildEmojiPickerItems() + + val bodyLayoutManager = + GridLayoutManager( + context, + emojiGridColumns, + LinearLayoutManager.VERTICAL, + /* reverseLayout = */ false + ) + .apply { + spanSizeLookup = + object : GridLayoutManager.SpanSizeLookup() { + override fun getSpanSize(position: Int): Int { + return when (emojiPickerItems.getBodyItem(position).itemType) { + ItemType.CATEGORY_TITLE, + ItemType.PLACEHOLDER_TEXT -> emojiGridColumns + else -> 1 + } + } + } + } + + val headerAdapter = + EmojiPickerHeaderAdapter( + context, + emojiPickerItems, + onHeaderIconClicked = { + with(emojiPickerItems.firstItemPositionByGroupIndex(it)) { + if (this == emojiPickerItems.groupRange(recentItemGroup).first) { + scope.launch { refreshRecent() } + } + bodyLayoutManager.scrollToPositionWithOffset(this, 0) + // The scroll position change will not be reflected until the next layout + // call, + // so force a new layout call here. + invalidate() + } + } + ) + + // clear view's children in case of resetting layout + super.removeAllViews() + with(inflate(context, R.layout.emoji_picker, this)) { + // set headerView + ViewCompat.requireViewById(this, R.id.emoji_picker_header).apply { + layoutManager = + object : LinearLayoutManager(context, HORIZONTAL, /* reverseLayout= */ false) { + override fun checkLayoutParams(lp: RecyclerView.LayoutParams): Boolean { + lp.width = + (width - paddingStart - paddingEnd) / emojiPickerItems.numGroups + return true + } + } + adapter = headerAdapter + } + + // set bodyView + ViewCompat.requireViewById(this, R.id.emoji_picker_body).apply { + layoutManager = bodyLayoutManager + adapter = + createEmojiPickerBodyAdapter() + .apply { setHasStableIds(true) } + .also { bodyAdapter = it } + addOnScrollListener( + object : RecyclerView.OnScrollListener() { + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + super.onScrolled(recyclerView, dx, dy) + headerAdapter.selectedGroupIndex = + emojiPickerItems.groupIndexByItemPosition( + bodyLayoutManager.findFirstCompletelyVisibleItemPosition() + ) + if ( + recentNeedsRefreshing && + bodyLayoutManager.findFirstVisibleItemPosition() !in + emojiPickerItems.groupRange(recentItemGroup) + ) { + scope.launch { refreshRecent() } + } + } + } + ) + // Disable item insertion/deletion animation. This keeps view holder unchanged when + // item updates. + itemAnimator = null + setRecycledViewPool( + RecyclerView.RecycledViewPool().apply { + setMaxRecycledViews( + ItemType.EMOJI.ordinal, + EmojiPickerConstants.EMOJI_VIEW_POOL_SIZE + ) + } + ) + } + } + } + + internal suspend fun refreshRecent() { + if (!recentNeedsRefreshing) { + return + } + val oldGroupSize = if (::recentItemGroup.isInitialized) recentItemGroup.size else 0 + val recent = recentEmojiProvider.getRecentEmojiList() + withContext(Dispatchers.Main) { + recentItems.clear() + recentItems.addAll( + recent.map { + EmojiViewData( + it, + updateToSticky = false, + ) + } + ) + if (::emojiPickerItems.isInitialized) { + val range = emojiPickerItems.groupRange(recentItemGroup) + if (recentItemGroup.size > oldGroupSize) { + bodyAdapter.notifyItemRangeInserted( + range.first + oldGroupSize, + recentItemGroup.size - oldGroupSize + ) + } else if (recentItemGroup.size < oldGroupSize) { + bodyAdapter.notifyItemRangeRemoved( + range.first + recentItemGroup.size, + oldGroupSize - recentItemGroup.size + ) + } + bodyAdapter.notifyItemRangeChanged( + range.first, + minOf(oldGroupSize, recentItemGroup.size) + ) + recentNeedsRefreshing = false + } + } + } + + /** + * This function is used to set the custom behavior after clicking on an emoji icon. Clients + * could specify their own behavior inside this function. + */ + fun setOnEmojiPickedListener(onEmojiPickedListener: Consumer?) { + this.onEmojiPickedListener = onEmojiPickedListener + } + + fun setRecentEmojiProvider(recentEmojiProvider: RecentEmojiProvider) { + this.recentEmojiProvider = recentEmojiProvider + scope.launch { + recentNeedsRefreshing = true + refreshRecent() + } + } + + /** + * The following functions disallow clients to add view to the EmojiPickerView + * + * @param child the child view to be added + * @throws UnsupportedOperationException + */ + override fun addView(child: View?) { + if (childCount > 0) + throw UnsupportedOperationException(EmojiPickerConstants.ADD_VIEW_EXCEPTION_MESSAGE) + else super.addView(child) + } + + /** + * @param child + * @param params + * @throws UnsupportedOperationException + */ + override fun addView(child: View?, params: ViewGroup.LayoutParams?) { + if (childCount > 0) + throw UnsupportedOperationException(EmojiPickerConstants.ADD_VIEW_EXCEPTION_MESSAGE) + else super.addView(child, params) + } + + /** + * @param child + * @param index + * @throws UnsupportedOperationException + */ + override fun addView(child: View?, index: Int) { + if (childCount > 0) + throw UnsupportedOperationException(EmojiPickerConstants.ADD_VIEW_EXCEPTION_MESSAGE) + else super.addView(child, index) + } + + /** + * @param child + * @param index + * @param params + * @throws UnsupportedOperationException + */ + override fun addView(child: View?, index: Int, params: ViewGroup.LayoutParams?) { + if (childCount > 0) + throw UnsupportedOperationException(EmojiPickerConstants.ADD_VIEW_EXCEPTION_MESSAGE) + else super.addView(child, index, params) + } + + /** + * @param child + * @param width + * @param height + * @throws UnsupportedOperationException + */ + override fun addView(child: View?, width: Int, height: Int) { + if (childCount > 0) + throw UnsupportedOperationException(EmojiPickerConstants.ADD_VIEW_EXCEPTION_MESSAGE) + else super.addView(child, width, height) + } + + /** + * The following functions disallow clients to remove view from the EmojiPickerView + * + * @throws UnsupportedOperationException + */ + override fun removeAllViews() { + throw UnsupportedOperationException(EmojiPickerConstants.REMOVE_VIEW_EXCEPTION_MESSAGE) + } + + /** + * @param child + * @throws UnsupportedOperationException + */ + override fun removeView(child: View?) { + throw UnsupportedOperationException(EmojiPickerConstants.REMOVE_VIEW_EXCEPTION_MESSAGE) + } + + /** + * @param index + * @throws UnsupportedOperationException + */ + override fun removeViewAt(index: Int) { + throw UnsupportedOperationException(EmojiPickerConstants.REMOVE_VIEW_EXCEPTION_MESSAGE) + } + + /** + * @param child + * @throws UnsupportedOperationException + */ + override fun removeViewInLayout(child: View?) { + throw UnsupportedOperationException(EmojiPickerConstants.REMOVE_VIEW_EXCEPTION_MESSAGE) + } + + /** + * @param start + * @param count + * @throws UnsupportedOperationException + */ + override fun removeViews(start: Int, count: Int) { + throw UnsupportedOperationException(EmojiPickerConstants.REMOVE_VIEW_EXCEPTION_MESSAGE) + } + + /** + * @param start + * @param count + * @throws UnsupportedOperationException + */ + override fun removeViewsInLayout(start: Int, count: Int) { + throw UnsupportedOperationException(EmojiPickerConstants.REMOVE_VIEW_EXCEPTION_MESSAGE) + } +} diff --git a/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiView.kt b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiView.kt new file mode 100644 index 000000000..d25831d89 --- /dev/null +++ b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiView.kt @@ -0,0 +1,187 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.emoji2.emojipicker + +import android.content.Context +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.graphics.Rect +import android.os.Build +import android.text.Layout +import android.text.Spanned +import android.text.StaticLayout +import android.text.TextPaint +import android.util.AttributeSet +import android.util.TypedValue +import android.view.View +import androidx.annotation.RequiresApi +import androidx.core.graphics.applyCanvas +import androidx.emoji2.text.EmojiCompat + +/** A customized view to support drawing emojis asynchronously. */ +internal class EmojiView +@JvmOverloads +constructor( + context: Context, + attrs: AttributeSet? = null, +) : View(context, attrs) { + + companion object { + private const val EMOJI_DRAW_TEXT_SIZE_SP = 30 + } + + init { + background = context.getDrawable(R.drawable.ripple_emoji_view) + importantForAccessibility = IMPORTANT_FOR_ACCESSIBILITY_YES + } + + internal var willDrawVariantIndicator: Boolean = true + + private val textPaint = + TextPaint(Paint.ANTI_ALIAS_FLAG or Paint.FILTER_BITMAP_FLAG).apply { + textSize = + TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_SP, + EMOJI_DRAW_TEXT_SIZE_SP.toFloat(), + context.resources.displayMetrics + ) + } + + private val offscreenCanvasBitmap: Bitmap = + with(textPaint.fontMetricsInt) { + val size = bottom - top + Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888) + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + val size = + minOf(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec)) - + context.resources.getDimensionPixelSize(R.dimen.emoji_picker_emoji_view_padding) + setMeasuredDimension(size, size) + } + + override fun draw(canvas: Canvas) { + super.draw(canvas) + canvas.run { + save() + scale( + width.toFloat() / offscreenCanvasBitmap.width, + height.toFloat() / offscreenCanvasBitmap.height + ) + drawBitmap(offscreenCanvasBitmap, 0f, 0f, null) + restore() + } + } + + var emoji: CharSequence? = null + set(value) { + field = value + post { + if (value != null) { + if (value == this.emoji) { + drawEmoji( + if (EmojiPickerView.emojiCompatLoaded) + EmojiCompat.get().process(value) ?: value + else value, + drawVariantIndicator = + willDrawVariantIndicator && + BundledEmojiListLoader.getEmojiVariantsLookup() + .containsKey(value) + ) + contentDescription = value + } + invalidate() + } else { + offscreenCanvasBitmap.eraseColor(Color.TRANSPARENT) + } + } + } + + private fun drawEmoji(emoji: CharSequence, drawVariantIndicator: Boolean) { + offscreenCanvasBitmap.eraseColor(Color.TRANSPARENT) + offscreenCanvasBitmap.applyCanvas { + if (emoji is Spanned) { + createStaticLayout(emoji, width).draw(this) + } else { + val textWidth = textPaint.measureText(emoji, 0, emoji.length) + drawText( + emoji, + /* start = */ 0, + /* end = */ emoji.length, + /* x = */ (width - textWidth) / 2, + /* y = */ -textPaint.fontMetrics.top, + textPaint, + ) + } + if (drawVariantIndicator) { + context + .getDrawable(R.drawable.variant_availability_indicator) + ?.apply { + val canvasWidth = this@applyCanvas.width + val canvasHeight = this@applyCanvas.height + val indicatorWidth = + context.resources.getDimensionPixelSize( + R.dimen.variant_availability_indicator_width + ) + val indicatorHeight = + context.resources.getDimensionPixelSize( + R.dimen.variant_availability_indicator_height + ) + bounds = + Rect( + canvasWidth - indicatorWidth, + canvasHeight - indicatorHeight, + canvasWidth, + canvasHeight + ) + }!! + .draw(this) + } + } + } + + @RequiresApi(23) + internal object Api23Impl { + fun createStaticLayout(emoji: Spanned, textPaint: TextPaint, width: Int): StaticLayout = + StaticLayout.Builder.obtain(emoji, 0, emoji.length, textPaint, width) + .apply { + setAlignment(Layout.Alignment.ALIGN_CENTER) + setLineSpacing(/* spacingAdd= */ 0f, /* spacingMult= */ 1f) + setIncludePad(false) + } + .build() + } + + private fun createStaticLayout(emoji: Spanned, width: Int): StaticLayout { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + return Api23Impl.createStaticLayout(emoji, textPaint, width) + } else { + @Suppress("DEPRECATION") + return StaticLayout( + emoji, + textPaint, + width, + Layout.Alignment.ALIGN_CENTER, + /* spacingmult = */ 1f, + /* spacingadd = */ 0f, + /* includepad = */ false, + ) + } + } +} diff --git a/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiViewHolder.kt b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiViewHolder.kt new file mode 100644 index 000000000..4a8714ea2 --- /dev/null +++ b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiViewHolder.kt @@ -0,0 +1,95 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.emoji2.emojipicker + +import android.content.Context +import android.view.View +import android.view.View.OnLongClickListener +import android.view.ViewGroup.LayoutParams +import android.view.accessibility.AccessibilityEvent +import androidx.recyclerview.widget.RecyclerView.ViewHolder + +/** A [ViewHolder] containing an emoji view and emoji data. */ +internal class EmojiViewHolder( + context: Context, + width: Int, + height: Int, + private val stickyVariantProvider: StickyVariantProvider, + private val onEmojiPickedListener: EmojiViewHolder.(EmojiViewItem) -> Unit, + private val onEmojiPickedFromPopupListener: EmojiViewHolder.(String) -> Unit +) : ViewHolder(EmojiView(context)) { + private val onEmojiLongClickListener: OnLongClickListener = + OnLongClickListener { targetEmojiView -> + showEmojiPopup(context, targetEmojiView) + } + + private val emojiView: EmojiView = + (itemView as EmojiView).apply { + layoutParams = LayoutParams(width, height) + isClickable = true + setOnClickListener { + it.sendAccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT) + onEmojiPickedListener(emojiViewItem) + } + } + private lateinit var emojiViewItem: EmojiViewItem + private lateinit var emojiPickerPopupViewController: EmojiPickerPopupViewController + + fun bindEmoji( + emoji: String, + ) { + emojiView.emoji = emoji + emojiViewItem = makeEmojiViewItem(emoji) + + if (emojiViewItem.variants.isNotEmpty()) { + emojiView.setOnLongClickListener(onEmojiLongClickListener) + emojiView.isLongClickable = true + } else { + emojiView.setOnLongClickListener(null) + emojiView.isLongClickable = false + } + } + + private fun showEmojiPopup(context: Context, clickedEmojiView: View): Boolean { + val emojiPickerPopupView = + EmojiPickerPopupView( + context, + /* attrs= */ null, + targetEmojiView = clickedEmojiView, + targetEmojiItem = emojiViewItem, + emojiViewOnClickListener = { view -> + val emojiPickedInPopup = (view as EmojiView).emoji.toString() + onEmojiPickedFromPopupListener(emojiPickedInPopup) + onEmojiPickedListener(makeEmojiViewItem(emojiPickedInPopup)) + // variants[0] is always the base (i.e., primary) emoji + stickyVariantProvider.update(emojiViewItem.variants[0], emojiPickedInPopup) + emojiPickerPopupViewController.dismiss() + // Hover on the base emoji after popup dismissed + clickedEmojiView.sendAccessibilityEvent( + AccessibilityEvent.TYPE_VIEW_HOVER_ENTER + ) + } + ) + emojiPickerPopupViewController = + EmojiPickerPopupViewController(context, emojiPickerPopupView, clickedEmojiView) + emojiPickerPopupViewController.show() + return true + } + + private fun makeEmojiViewItem(emoji: String) = + EmojiViewItem(emoji, BundledEmojiListLoader.getEmojiVariantsLookup()[emoji] ?: listOf()) +} diff --git a/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiViewItem.kt b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiViewItem.kt new file mode 100644 index 000000000..e6121f13f --- /dev/null +++ b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/EmojiViewItem.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.emoji2.emojipicker + +/** + * [EmojiViewItem] is a class holding the displayed emoji and its emoji variants + * + * @param emoji Used to represent the displayed emoji of the [EmojiViewItem]. + * @param variants Used to represent the corresponding emoji variants of this base emoji. + */ +class EmojiViewItem(val emoji: String, val variants: List) diff --git a/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/ItemViewData.kt b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/ItemViewData.kt new file mode 100644 index 000000000..8bf6bcbca --- /dev/null +++ b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/ItemViewData.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.emoji2.emojipicker + +internal enum class ItemType { + CATEGORY_TITLE, + PLACEHOLDER_TEXT, + EMOJI, +} + +/** Represents an item within the body RecyclerView. */ +internal sealed class ItemViewData(val itemType: ItemType) { + val viewType = itemType.ordinal +} + +/** Title of each category. */ +internal data class CategoryTitle(val title: String) : ItemViewData(ItemType.CATEGORY_TITLE) + +/** Text to display when the category contains no items. */ +internal data class PlaceholderText(val text: String) : ItemViewData(ItemType.PLACEHOLDER_TEXT) + +/** Represents an emoji. */ +internal data class EmojiViewData( + var emoji: String, + val updateToSticky: Boolean = true, + // Needed to ensure uniqueness since we enabled stable Id. + val dataIndex: Int = 0 +) : ItemViewData(ItemType.EMOJI) + +internal object Extensions { + internal fun Int.toItemType() = ItemType.values()[this] +} diff --git a/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/RecentEmojiAsyncProvider.kt b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/RecentEmojiAsyncProvider.kt new file mode 100644 index 000000000..3661dd3ad --- /dev/null +++ b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/RecentEmojiAsyncProvider.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.emoji2.emojipicker + +import com.google.common.util.concurrent.ListenableFuture +import kotlinx.coroutines.guava.await + +/** + * A interface equivalent to [RecentEmojiProvider] that allows java clients to override the + * [ListenableFuture] based function [getRecentEmojiListAsync] in order to provide recent emojis. + */ +interface RecentEmojiAsyncProvider { + fun recordSelection(emoji: String) + + fun getRecentEmojiListAsync(): ListenableFuture> +} + +/** An adapter for the [RecentEmojiAsyncProvider]. */ +class RecentEmojiProviderAdapter(private val recentEmojiAsyncProvider: RecentEmojiAsyncProvider) : + RecentEmojiProvider { + override fun recordSelection(emoji: String) { + recentEmojiAsyncProvider.recordSelection(emoji) + } + + override suspend fun getRecentEmojiList() = + recentEmojiAsyncProvider.getRecentEmojiListAsync().await() +} diff --git a/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/RecentEmojiProvider.kt b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/RecentEmojiProvider.kt new file mode 100644 index 000000000..edccc6371 --- /dev/null +++ b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/RecentEmojiProvider.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.emoji2.emojipicker + +/** An interface to provide recent emoji list. */ +interface RecentEmojiProvider { + /** + * Records an emoji into recent emoji list. This fun will be called when an emoji is selected. + * Clients could specify the behavior to record recently used emojis.(e.g. click frequency). + */ + fun recordSelection(emoji: String) + + /** + * Returns a list of recent emojis. Default behavior: The most recently used emojis will be + * displayed first. Clients could also specify the behavior such as displaying the emojis from + * high click frequency to low click frequency. + */ + suspend fun getRecentEmojiList(): List +} diff --git a/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/StickyVariantProvider.kt b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/StickyVariantProvider.kt new file mode 100644 index 000000000..39653d9cd --- /dev/null +++ b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/StickyVariantProvider.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.emoji2.emojipicker + +import android.content.Context +import android.content.Context.MODE_PRIVATE + +/** A class that handles user's emoji variant selection using SharedPreferences. */ +internal class StickyVariantProvider(context: Context) { + companion object { + const val PREFERENCES_FILE_NAME = "androidx.emoji2.emojipicker.preferences" + const val STICKY_VARIANT_PROVIDER_KEY = "pref_key_sticky_variant" + const val KEY_VALUE_DELIMITER = "=" + const val ENTRY_DELIMITER = "|" + } + + private val sharedPreferences = + context.getSharedPreferences(PREFERENCES_FILE_NAME, MODE_PRIVATE) + + private val stickyVariantMap: MutableMap by lazy { + sharedPreferences + .getString(STICKY_VARIANT_PROVIDER_KEY, null) + ?.split(ENTRY_DELIMITER) + ?.associate { entry -> + entry + .split(KEY_VALUE_DELIMITER, limit = 2) + .takeIf { it.size == 2 } + ?.let { it[0] to it[1] } ?: ("" to "") + } + ?.toMutableMap() ?: mutableMapOf() + } + + internal operator fun get(emoji: String): String = stickyVariantMap[emoji] ?: emoji + + internal fun update(baseEmoji: String, variantClicked: String) { + stickyVariantMap.apply { + if (baseEmoji == variantClicked) { + this.remove(baseEmoji) + } else { + this[baseEmoji] = variantClicked + } + sharedPreferences + .edit() + .putString(STICKY_VARIANT_PROVIDER_KEY, entries.joinToString(ENTRY_DELIMITER)) + .commit() + } + } +} diff --git a/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/utils/FileCache.kt b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/utils/FileCache.kt new file mode 100644 index 000000000..01b2e08b3 --- /dev/null +++ b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/utils/FileCache.kt @@ -0,0 +1,149 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.emoji2.emojipicker.utils + +import android.content.Context +import android.content.pm.PackageManager +import android.os.Build +import android.util.Log +import androidx.annotation.GuardedBy +import androidx.annotation.RequiresApi +import androidx.annotation.VisibleForTesting +import androidx.core.content.ContextCompat +import androidx.emoji2.emojipicker.BundledEmojiListLoader +import androidx.emoji2.emojipicker.EmojiViewItem +import java.io.File +import java.io.IOException + +/** + * A class that manages cache files for the emoji picker. All cache files are stored in DE (Device + * Encryption) storage (N+), and will be invalidated if device OS version or App version is updated. + * + * Currently this class is only used by [BundledEmojiListLoader]. All renderable emojis will be + * cached by categories under /app.package.name/cache/emoji_picker/ + * /emoji.... + */ +internal class FileCache(context: Context) { + + @VisibleForTesting @GuardedBy("lock") internal val emojiPickerCacheDir: File + private val currentProperty: String + private val lock = Any() + + init { + val osVersion = "${Build.VERSION.SDK_INT}_${Build.TIME}" + val appVersion = getVersionCode(context) + currentProperty = "$osVersion.$appVersion" + emojiPickerCacheDir = + File(getDeviceProtectedStorageContext(context).cacheDir, EMOJI_PICKER_FOLDER) + if (!emojiPickerCacheDir.exists()) emojiPickerCacheDir.mkdir() + } + + /** Get cache for a given file name, or write to a new file using the [defaultValue] factory. */ + internal fun getOrPut( + key: String, + defaultValue: () -> List + ): List { + synchronized(lock) { + val targetDir = File(emojiPickerCacheDir, currentProperty) + // No matching cache folder for current property, clear stale cache directory if any + if (!targetDir.exists()) { + emojiPickerCacheDir.listFiles()?.forEach { it.deleteRecursively() } + targetDir.mkdirs() + } + + val targetFile = File(targetDir, key) + return readFrom(targetFile) ?: writeTo(targetFile, defaultValue) + } + } + + private fun readFrom(targetFile: File): List? { + if (!targetFile.isFile) return null + return targetFile + .bufferedReader() + .useLines { it.toList() } + .map { it.split(",") } + .map { EmojiViewItem(it.first(), it.drop(1)) } + } + + private fun writeTo( + targetFile: File, + defaultValue: () -> List + ): List { + val data = defaultValue.invoke() + if (targetFile.exists()) { + if (!targetFile.delete()) { + Log.wtf(TAG, "Can't delete file: $targetFile") + } + } + if (!targetFile.createNewFile()) { + throw IOException("Can't create file: $targetFile") + } + targetFile.bufferedWriter().use { out -> + for (emoji in data) { + out.write(emoji.emoji) + emoji.variants.forEach { out.write(",$it") } + out.newLine() + } + } + return data + } + + /** Returns a new [context] for accessing device protected storage. */ + private fun getDeviceProtectedStorageContext(context: Context) = + context.takeIf { ContextCompat.isDeviceProtectedStorage(it) } + ?: run { ContextCompat.createDeviceProtectedStorageContext(context) } + ?: context + + /** Gets the version code for a package. */ + @Suppress("DEPRECATION") + private fun getVersionCode(context: Context): Long = + try { + if (Build.VERSION.SDK_INT >= 33) Api33Impl.getAppVersionCode(context) + else if (Build.VERSION.SDK_INT >= 28) Api28Impl.getAppVersionCode(context) + else context.packageManager.getPackageInfo(context.packageName, 0).versionCode.toLong() + } catch (e: PackageManager.NameNotFoundException) { + // Default version to 1 + 1 + } + + companion object { + @Volatile private var instance: FileCache? = null + + internal fun getInstance(context: Context): FileCache = + instance ?: synchronized(this) { instance ?: FileCache(context).also { instance = it } } + + private const val EMOJI_PICKER_FOLDER = "emoji_picker" + private const val TAG = "emojipicker.FileCache" + } + + @RequiresApi(Build.VERSION_CODES.TIRAMISU) + internal object Api33Impl { + fun getAppVersionCode(context: Context) = + context.packageManager + .getPackageInfo(context.packageName, PackageManager.PackageInfoFlags.of(0)) + .longVersionCode + } + + @Suppress("DEPRECATION") + @RequiresApi(Build.VERSION_CODES.P) + internal object Api28Impl { + fun getAppVersionCode(context: Context) = + context.packageManager + .getPackageInfo(context.packageName, /* flags= */ 0) + .longVersionCode + } +} diff --git a/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/utils/UnicodeRenderableManager.kt b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/utils/UnicodeRenderableManager.kt new file mode 100644 index 000000000..d13af5419 --- /dev/null +++ b/emojipicker/app/src/main/androidx/java/androidx/emoji2/emojipicker/utils/UnicodeRenderableManager.kt @@ -0,0 +1,83 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.emoji2.emojipicker.utils + +import android.os.Build +import android.text.TextPaint +import androidx.annotation.VisibleForTesting +import androidx.core.graphics.PaintCompat +import androidx.emoji2.emojipicker.EmojiPickerView +import androidx.emoji2.text.EmojiCompat + +/** Checks renderability of unicode characters. */ +internal object UnicodeRenderableManager { + + private const val VARIATION_SELECTOR = "\uFE0F" + + private const val YAWNING_FACE_EMOJI = "\uD83E\uDD71" + + private val paint = TextPaint() + + /** + * Some emojis were usual (non-emoji) characters. Old devices cannot render them with variation + * selector (U+FE0F) so it's worth trying to check renderability again without variation + * selector. + */ + private val CATEGORY_MOVED_EMOJIS = + listOf( // These three characters have been emoji since Unicode emoji version 4. + // version 3: https://unicode.org/Public/emoji/3.0/emoji-data.txt + // version 4: https://unicode.org/Public/emoji/4.0/emoji-data.txt + "\u2695\uFE0F", // STAFF OF AESCULAPIUS + "\u2640\uFE0F", // FEMALE SIGN + "\u2642\uFE0F", // MALE SIGN + // These three characters have been emoji since Unicode emoji version 11. + // version 5: https://unicode.org/Public/emoji/5.0/emoji-data.txt + // version 11: https://unicode.org/Public/emoji/11.0/emoji-data.txt + "\u265F\uFE0F", // BLACK_CHESS_PAWN + "\u267E\uFE0F" // PERMANENT_PAPER_SIGN + ) + + /** + * For a given emoji, check it's renderability with EmojiCompat if enabled. Otherwise, use + * [PaintCompat#hasGlyph]. + * + * Note: For older API version, codepoints {@code U+0xFE0F} are removed. + */ + internal fun isEmojiRenderable(emoji: String) = + if (EmojiPickerView.emojiCompatLoaded) + EmojiCompat.get().getEmojiMatch(emoji, Int.MAX_VALUE) == EmojiCompat.EMOJI_SUPPORTED + else getClosestRenderable(emoji) != null + + // Yawning face is added in emoji 12 which is the first version starts to support gender + // inclusive emojis. + internal fun isEmoji12Supported() = isEmojiRenderable(YAWNING_FACE_EMOJI) + + @VisibleForTesting + fun getClosestRenderable(emoji: String): String? { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + return emoji.replace(VARIATION_SELECTOR, "").takeIfHasGlyph() + } + return emoji.takeIfHasGlyph() + ?: run { + if (CATEGORY_MOVED_EMOJIS.contains(emoji)) + emoji.replace(VARIATION_SELECTOR, "").takeIfHasGlyph() + else null + } + } + + private fun String.takeIfHasGlyph() = takeIf { PaintCompat.hasGlyph(paint, this) } +} diff --git a/emojipicker/app/src/main/androidx/res/anim/slide_down_and_fade_out.xml b/emojipicker/app/src/main/androidx/res/anim/slide_down_and_fade_out.xml new file mode 100644 index 000000000..39f3163ed --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/anim/slide_down_and_fade_out.xml @@ -0,0 +1,31 @@ + + + + + + + + \ No newline at end of file diff --git a/emojipicker/app/src/main/androidx/res/anim/slide_up_and_fade_in.xml b/emojipicker/app/src/main/androidx/res/anim/slide_up_and_fade_in.xml new file mode 100644 index 000000000..5dad0a8e5 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/anim/slide_up_and_fade_in.xml @@ -0,0 +1,31 @@ + + + + + + + + \ No newline at end of file diff --git a/emojipicker/app/src/main/androidx/res/drawable/couple_heart_men_shadow_skintone.xml b/emojipicker/app/src/main/androidx/res/drawable/couple_heart_men_shadow_skintone.xml new file mode 100644 index 000000000..e480cbf52 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/couple_heart_men_shadow_skintone.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/couple_heart_men_skintone_shadow.xml b/emojipicker/app/src/main/androidx/res/drawable/couple_heart_men_skintone_shadow.xml new file mode 100644 index 000000000..6d54233c9 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/couple_heart_men_skintone_shadow.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/couple_heart_people_shadow_skintone.xml b/emojipicker/app/src/main/androidx/res/drawable/couple_heart_people_shadow_skintone.xml new file mode 100644 index 000000000..219fb0aa5 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/couple_heart_people_shadow_skintone.xml @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/emojipicker/app/src/main/androidx/res/drawable/couple_heart_people_skintone_shadow.xml b/emojipicker/app/src/main/androidx/res/drawable/couple_heart_people_skintone_shadow.xml new file mode 100644 index 000000000..09e95e563 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/couple_heart_people_skintone_shadow.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/couple_heart_woman_man_shadow_skintone.xml b/emojipicker/app/src/main/androidx/res/drawable/couple_heart_woman_man_shadow_skintone.xml new file mode 100644 index 000000000..1107c60cf --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/couple_heart_woman_man_shadow_skintone.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/couple_heart_woman_man_skintone_shadow.xml b/emojipicker/app/src/main/androidx/res/drawable/couple_heart_woman_man_skintone_shadow.xml new file mode 100644 index 000000000..1334b6771 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/couple_heart_woman_man_skintone_shadow.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/couple_heart_women_shadow_skintone.xml b/emojipicker/app/src/main/androidx/res/drawable/couple_heart_women_shadow_skintone.xml new file mode 100644 index 000000000..4fe76d7d1 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/couple_heart_women_shadow_skintone.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/couple_heart_women_skintone_shadow.xml b/emojipicker/app/src/main/androidx/res/drawable/couple_heart_women_skintone_shadow.xml new file mode 100644 index 000000000..b8b660094 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/couple_heart_women_skintone_shadow.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/gm_filled_emoji_emotions_vd_theme_24.xml b/emojipicker/app/src/main/androidx/res/drawable/gm_filled_emoji_emotions_vd_theme_24.xml new file mode 100644 index 000000000..ba3a86882 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/gm_filled_emoji_emotions_vd_theme_24.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/gm_filled_emoji_events_vd_theme_24.xml b/emojipicker/app/src/main/androidx/res/drawable/gm_filled_emoji_events_vd_theme_24.xml new file mode 100644 index 000000000..864a0cdaa --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/gm_filled_emoji_events_vd_theme_24.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/gm_filled_emoji_food_beverage_vd_theme_24.xml b/emojipicker/app/src/main/androidx/res/drawable/gm_filled_emoji_food_beverage_vd_theme_24.xml new file mode 100644 index 000000000..e7722102d --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/gm_filled_emoji_food_beverage_vd_theme_24.xml @@ -0,0 +1,29 @@ + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/gm_filled_emoji_nature_vd_theme_24.xml b/emojipicker/app/src/main/androidx/res/drawable/gm_filled_emoji_nature_vd_theme_24.xml new file mode 100644 index 000000000..7d9d06b4c --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/gm_filled_emoji_nature_vd_theme_24.xml @@ -0,0 +1,29 @@ + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/gm_filled_emoji_objects_vd_theme_24.xml b/emojipicker/app/src/main/androidx/res/drawable/gm_filled_emoji_objects_vd_theme_24.xml new file mode 100644 index 000000000..0e38ec46f --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/gm_filled_emoji_objects_vd_theme_24.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/gm_filled_emoji_people_vd_theme_24.xml b/emojipicker/app/src/main/androidx/res/drawable/gm_filled_emoji_people_vd_theme_24.xml new file mode 100644 index 000000000..882a024f2 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/gm_filled_emoji_people_vd_theme_24.xml @@ -0,0 +1,29 @@ + + + + + + \ No newline at end of file diff --git a/emojipicker/app/src/main/androidx/res/drawable/gm_filled_emoji_symbols_vd_theme_24.xml b/emojipicker/app/src/main/androidx/res/drawable/gm_filled_emoji_symbols_vd_theme_24.xml new file mode 100644 index 000000000..0cbe0eafb --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/gm_filled_emoji_symbols_vd_theme_24.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/gm_filled_emoji_transportation_vd_theme_24.xml b/emojipicker/app/src/main/androidx/res/drawable/gm_filled_emoji_transportation_vd_theme_24.xml new file mode 100644 index 000000000..63d969934 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/gm_filled_emoji_transportation_vd_theme_24.xml @@ -0,0 +1,41 @@ + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/gm_filled_flag_vd_theme_24.xml b/emojipicker/app/src/main/androidx/res/drawable/gm_filled_flag_vd_theme_24.xml new file mode 100644 index 000000000..a5ebe269d --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/gm_filled_flag_vd_theme_24.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/handshake_shadow_skintone.xml b/emojipicker/app/src/main/androidx/res/drawable/handshake_shadow_skintone.xml new file mode 100644 index 000000000..04259f359 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/handshake_shadow_skintone.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/handshake_skintone_shadow.xml b/emojipicker/app/src/main/androidx/res/drawable/handshake_skintone_shadow.xml new file mode 100644 index 000000000..dfe4f213c --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/handshake_skintone_shadow.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/holding_men_shadow_skintone.xml b/emojipicker/app/src/main/androidx/res/drawable/holding_men_shadow_skintone.xml new file mode 100644 index 000000000..4b84e94a6 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/holding_men_shadow_skintone.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/holding_men_skintone_shadow.xml b/emojipicker/app/src/main/androidx/res/drawable/holding_men_skintone_shadow.xml new file mode 100644 index 000000000..e9def1c60 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/holding_men_skintone_shadow.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/holding_people_shadow_skintone.xml b/emojipicker/app/src/main/androidx/res/drawable/holding_people_shadow_skintone.xml new file mode 100644 index 000000000..ebbd0f4cf --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/holding_people_shadow_skintone.xml @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/holding_people_skintone_shadow.xml b/emojipicker/app/src/main/androidx/res/drawable/holding_people_skintone_shadow.xml new file mode 100644 index 000000000..039b6207d --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/holding_people_skintone_shadow.xml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/holding_woman_man_shadow_skintone.xml b/emojipicker/app/src/main/androidx/res/drawable/holding_woman_man_shadow_skintone.xml new file mode 100644 index 000000000..a921ec264 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/holding_woman_man_shadow_skintone.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/holding_woman_man_skintone_shadow.xml b/emojipicker/app/src/main/androidx/res/drawable/holding_woman_man_skintone_shadow.xml new file mode 100644 index 000000000..85c332764 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/holding_woman_man_skintone_shadow.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/holding_women_shadow_skintone.xml b/emojipicker/app/src/main/androidx/res/drawable/holding_women_shadow_skintone.xml new file mode 100644 index 000000000..0e918b995 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/holding_women_shadow_skintone.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/holding_women_skintone_shadow.xml b/emojipicker/app/src/main/androidx/res/drawable/holding_women_skintone_shadow.xml new file mode 100644 index 000000000..035cc21ea --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/holding_women_skintone_shadow.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/icon_tint_selector.xml b/emojipicker/app/src/main/androidx/res/drawable/icon_tint_selector.xml new file mode 100644 index 000000000..c1531b66e --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/icon_tint_selector.xml @@ -0,0 +1,20 @@ + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/kiss_men_shadow_skintone.xml b/emojipicker/app/src/main/androidx/res/drawable/kiss_men_shadow_skintone.xml new file mode 100644 index 000000000..e3df38d56 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/kiss_men_shadow_skintone.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/kiss_men_skintone_shadow.xml b/emojipicker/app/src/main/androidx/res/drawable/kiss_men_skintone_shadow.xml new file mode 100644 index 000000000..2abbd8842 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/kiss_men_skintone_shadow.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/kiss_people_shadow_skintone.xml b/emojipicker/app/src/main/androidx/res/drawable/kiss_people_shadow_skintone.xml new file mode 100644 index 000000000..ddaa48390 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/kiss_people_shadow_skintone.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/kiss_people_skintone_shadow.xml b/emojipicker/app/src/main/androidx/res/drawable/kiss_people_skintone_shadow.xml new file mode 100644 index 000000000..f81d8633d --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/kiss_people_skintone_shadow.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/kiss_woman_man_shadow_skintone.xml b/emojipicker/app/src/main/androidx/res/drawable/kiss_woman_man_shadow_skintone.xml new file mode 100644 index 000000000..118312377 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/kiss_woman_man_shadow_skintone.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/kiss_woman_man_skintone_shadow.xml b/emojipicker/app/src/main/androidx/res/drawable/kiss_woman_man_skintone_shadow.xml new file mode 100644 index 000000000..5ded1f960 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/kiss_woman_man_skintone_shadow.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/kiss_women_shadow_skintone.xml b/emojipicker/app/src/main/androidx/res/drawable/kiss_women_shadow_skintone.xml new file mode 100644 index 000000000..555d28cd5 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/kiss_women_shadow_skintone.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/kiss_women_skintone_shadow.xml b/emojipicker/app/src/main/androidx/res/drawable/kiss_women_skintone_shadow.xml new file mode 100644 index 000000000..61d91624b --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/kiss_women_skintone_shadow.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/popup_view_rounded_background.xml b/emojipicker/app/src/main/androidx/res/drawable/popup_view_rounded_background.xml new file mode 100644 index 000000000..65b86b306 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/popup_view_rounded_background.xml @@ -0,0 +1,21 @@ + + + + + + + \ No newline at end of file diff --git a/emojipicker/app/src/main/androidx/res/drawable/quantum_gm_ic_access_time_filled_vd_theme_24.xml b/emojipicker/app/src/main/androidx/res/drawable/quantum_gm_ic_access_time_filled_vd_theme_24.xml new file mode 100644 index 000000000..28aa933eb --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/quantum_gm_ic_access_time_filled_vd_theme_24.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/ripple_emoji_view.xml b/emojipicker/app/src/main/androidx/res/drawable/ripple_emoji_view.xml new file mode 100644 index 000000000..f42fea4aa --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/ripple_emoji_view.xml @@ -0,0 +1,25 @@ + + + + + + + + + + \ No newline at end of file diff --git a/emojipicker/app/src/main/androidx/res/drawable/ripple_image_view.xml b/emojipicker/app/src/main/androidx/res/drawable/ripple_image_view.xml new file mode 100644 index 000000000..4c0c3a46d --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/ripple_image_view.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/swap_horiz_vd_theme_24.xml b/emojipicker/app/src/main/androidx/res/drawable/swap_horiz_vd_theme_24.xml new file mode 100644 index 000000000..e3684d49f --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/swap_horiz_vd_theme_24.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/emojipicker/app/src/main/androidx/res/drawable/underline_rounded.xml b/emojipicker/app/src/main/androidx/res/drawable/underline_rounded.xml new file mode 100644 index 000000000..df2aecec5 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/underline_rounded.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/emojipicker/app/src/main/androidx/res/drawable/variant_availability_indicator.xml b/emojipicker/app/src/main/androidx/res/drawable/variant_availability_indicator.xml new file mode 100644 index 000000000..7415fab25 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/drawable/variant_availability_indicator.xml @@ -0,0 +1,26 @@ + + + + + \ No newline at end of file diff --git a/emojipicker/app/src/main/androidx/res/layout/category_text_view.xml b/emojipicker/app/src/main/androidx/res/layout/category_text_view.xml new file mode 100644 index 000000000..d5ee11de4 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/layout/category_text_view.xml @@ -0,0 +1,35 @@ + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/layout/emoji_picker.xml b/emojipicker/app/src/main/androidx/res/layout/emoji_picker.xml new file mode 100644 index 000000000..84192cc86 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/layout/emoji_picker.xml @@ -0,0 +1,33 @@ + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/layout/emoji_picker_popup_bidirectional.xml b/emojipicker/app/src/main/androidx/res/layout/emoji_picker_popup_bidirectional.xml new file mode 100644 index 000000000..be0c3df79 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/layout/emoji_picker_popup_bidirectional.xml @@ -0,0 +1,26 @@ + + + diff --git a/emojipicker/app/src/main/androidx/res/layout/emoji_picker_popup_emoji_view.xml b/emojipicker/app/src/main/androidx/res/layout/emoji_picker_popup_emoji_view.xml new file mode 100644 index 000000000..d50dd939b --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/layout/emoji_picker_popup_emoji_view.xml @@ -0,0 +1,32 @@ + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/layout/emoji_picker_popup_image_view.xml b/emojipicker/app/src/main/androidx/res/layout/emoji_picker_popup_image_view.xml new file mode 100644 index 000000000..da10bf120 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/layout/emoji_picker_popup_image_view.xml @@ -0,0 +1,27 @@ + + + + diff --git a/emojipicker/app/src/main/androidx/res/layout/empty_category_text_view.xml b/emojipicker/app/src/main/androidx/res/layout/empty_category_text_view.xml new file mode 100644 index 000000000..71a759123 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/layout/empty_category_text_view.xml @@ -0,0 +1,25 @@ + + + diff --git a/emojipicker/app/src/main/androidx/res/layout/header_icon_holder.xml b/emojipicker/app/src/main/androidx/res/layout/header_icon_holder.xml new file mode 100644 index 000000000..dd4ba7439 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/layout/header_icon_holder.xml @@ -0,0 +1,38 @@ + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/layout/variant_popup.xml b/emojipicker/app/src/main/androidx/res/layout/variant_popup.xml new file mode 100644 index 000000000..3a90b1816 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/layout/variant_popup.xml @@ -0,0 +1,27 @@ + + + + \ No newline at end of file diff --git a/emojipicker/app/src/main/androidx/res/raw/emoji_category_activity.csv b/emojipicker/app/src/main/androidx/res/raw/emoji_category_activity.csv new file mode 100644 index 000000000..ff009b322 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/raw/emoji_category_activity.csv @@ -0,0 +1,115 @@ +🎉 +🎊 +🎈 +🎂 +🎀 +🎁 +🎇 +🎆 +🧨 +🧧 +🪔 +🪅 +🪩 +🎐 +🎏 +🎎 +🎑 +🎍 +🎋 +🎄 +🎃 +🎗️ +🥇 +🥈 +🥉 +🏅 +🎖️ +🏆 +📢 +⚽ +⚾ +🥎 +🏀 +🏐 +🏈 +🏉 +🥅 +🎾 +🏸 +🥍 +🏏 +🏑 +🏒 +🥌 +🛷 +🎿 +⛸️ +🛼 +🩰 +🛹 +⛳ +🎯 +🏹 +🥏 +🪃 +🪁 +🎣 +🤿 +🩱 +🎽 +🥋 +🥊 +🎱 +🏓 +🎳 +♟️ +🪀 +🧩 +🎮 +🕹️ +👾 +🔫 +🎲 +🎰 +🎴 +🀄 +🃏 +🪄 +🎩 +📷 +📸 +🖼️ +🎨 +🖌️ +🖍️ +🪡 +🧵 +🧶 +🎹 +🎷 +🎺 +🎸 +🪕 +🎻 +🪘 +🥁 +🪇 +🪈 +🪗 +🎤 +🎧 +🎚️ +🎛️ +🎙️ +📻 +📺 +📼 +📹 +📽️ +🎥 +🎞️ +🎬 +🎭 +🎫 +🎟️ diff --git a/emojipicker/app/src/main/androidx/res/raw/emoji_category_animals_nature.csv b/emojipicker/app/src/main/androidx/res/raw/emoji_category_animals_nature.csv new file mode 100644 index 000000000..40a39944a --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/raw/emoji_category_animals_nature.csv @@ -0,0 +1,223 @@ +💐 +🌹 +🥀 +🌺 +🌷 +🪷 +🌸 +💮 +🏵️ +🪻 +🌻 +🌼 +🍂 +🍁 +🍄 +🌾 +🌱 +🌿 +🍃 +☘️ +🍀 +🪴 +🌵 +🌴 +🌳 +🌲 +🪵 +🪹 +🪺 +🪨 +⛰️ +🏔️ +❄️ +☃️ +⛄ +🌫️ +🌡️ +🔥 +🌋 +🏜️ +🏞️ +🏝️ +🏖️ +🌅 +🌄 +🌈 +🫧 +🌊 +🌬️ +🌀 +🌪️ +⚡ +☔ +💧 +☁️ +🌨️ +🌧️ +🌩️ +⛈️ +🌦️ +🌥️ +⛅ +🌤️ +☀️ +🌞 +🌝 +🌚 +🌜 +🌛 +⭐ +🌟 +✨ +💫 +🌙 +☄️ +🕳️ +🌠 +🌌 +🌍 +🌎 +🌏 +🪐 +🌑 +🌒 +🌓 +🌔 +🌕 +🌖 +🌗 +🌘 +🙈 +🙉 +🙊 +🐵 +🦁 +🐯 +🐱 +🐶 +🐺 +🐻 +🐻‍❄️ +🐨 +🐼 +🐹 +🐭 +🐰 +🦊 +🦝 +🐮 +🐷 +🐽 +🐗 +🦓 +🦄 +🐴 +🫎 +🐲 +🦎 +🐉 +🦖 +🦕 +🐢 +🐊 +🐍 +🐸 +🐇 +🐁 +🐀 +🐈 +🐈‍⬛ +🐩 +🐕 +🦮 +🐕‍🦺 +🐖 +🐎 +🫏 +🐄 +🐂 +🐃 +🦬 +🐏 +🐑 +🐐 +🦌 +🦙 +🦥 +🦘 +🐘 +🦣 +🦏 +🦛 +🦒 +🐆 +🐅 +🐒 +🦍 +🦧 +🐪 +🐫 +🐿️ +🦫 +🦨 +🦡 +🦔 +🦦 +🦇 +🪽 +🪶 +🐦 +🐦‍⬛ +🐓 +🐔 +🐣 +🐤 +🐥 +🦅 +🦉 +🦜 +🕊️ +🦤 +🦢 +🦆 +🪿 +🦩 +🦚 +🐦‍🔥 +🦃 +🐧 +🦭 +🦈 +🐬 +🐋 +🐳 +🐟 +🐠 +🐡 +🦐 +🦞 +🦀 +🦑 +🐙 +🪼 +🦪 +🪸 +🦂 +🕷️ +🕸️ +🐚 +🐌 +🐜 +🦗 +🪲 +🦟 +🪳 +🪰 +🐝 +🐞 +🦋 +🐛 +🪱 +🦠 +🐾 diff --git a/emojipicker/app/src/main/androidx/res/raw/emoji_category_emotions.csv b/emojipicker/app/src/main/androidx/res/raw/emoji_category_emotions.csv new file mode 100644 index 000000000..176daa675 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/raw/emoji_category_emotions.csv @@ -0,0 +1,242 @@ +😀 +😃 +😄 +😁 +😆 +😅 +😂 +🤣 +😭 +😉 +😗 +😙 +😚 +😘 +🥰 +😍 +🤩 +🥳 +🫠 +🙃 +🙂 +🥲 +🥹 +😊 +☺️ +😌 +🙂‍↕️ +🙂‍↔️ +😏 +🤤 +😋 +😛 +😝 +😜 +🤪 +🥴 +😔 +🥺 +😬 +😑 +😐 +😶 +😶‍🌫️ +🫥 +🤐 +🫡 +🤔 +🤫 +🫢 +🤭 +🥱 +🤗 +🫣 +😱 +🤨 +🧐 +😒 +🙄 +😮‍💨 +😤 +😠 +😡 +🤬 +😞 +😓 +😟 +😥 +😢 +☹️ +🙁 +🫤 +😕 +😰 +😨 +😧 +😦 +😮 +😯 +😲 +😳 +🤯 +😖 +😣 +😩 +😫 +😵 +😵‍💫 +🫨 +🥶 +🥵 +🤢 +🤮 +😴 +😪 +🤧 +🤒 +🤕 +😷 +🤥 +😇 +🤠 +🤑 +🤓 +😎 +🥸 +🤡 +😈 +👿 +👻 +💀 +☠️ +👹 +👺 +🎃 +💩 +🤖 +👽 +👾 +🌚 +🌝 +🌞 +🌛 +🌜 +🙈 +🙉 +🙊 +😺 +😸 +😹 +😻 +😼 +😽 +🙀 +😿 +😾 +💫 +⭐ +🌟 +✨ +💥 +💨 +💦 +💤 +🕳️ +🔥 +💯 +🎉 +❤️ +🧡 +💛 +💚 +🩵 +💙 +💜 +🤎 +🖤 +🩶 +🤍 +🩷 +💘 +💝 +💖 +💗 +💓 +💞 +💕 +💌 +💟 +♥️ +❣️ +❤️‍🩹 +💔 +❤️‍🔥 +💋 +🫂 +👥 +👤 +🗣️ +👣 +🧠 +🫀 +🫁 +🩸 +🦠 +🦷 +🦴 +👀 +👁️ +👄 +🫦 +👅 +👃,👃,👃🏻,👃🏼,👃🏽,👃🏾,👃🏿 +👂,👂,👂🏻,👂🏼,👂🏽,👂🏾,👂🏿 +🦻,🦻,🦻🏻,🦻🏼,🦻🏽,🦻🏾,🦻🏿 +🦶,🦶,🦶🏻,🦶🏼,🦶🏽,🦶🏾,🦶🏿 +🦵,🦵,🦵🏻,🦵🏼,🦵🏽,🦵🏾,🦵🏿 +🦿 +🦾 +💪,💪,💪🏻,💪🏼,💪🏽,💪🏾,💪🏿 +👏,👏,👏🏻,👏🏼,👏🏽,👏🏾,👏🏿 +👍,👍,👍🏻,👍🏼,👍🏽,👍🏾,👍🏿 +👎,👎,👎🏻,👎🏼,👎🏽,👎🏾,👎🏿 +🫶,🫶,🫶🏻,🫶🏼,🫶🏽,🫶🏾,🫶🏿 +🙌,🙌,🙌🏻,🙌🏼,🙌🏽,🙌🏾,🙌🏿 +👐,👐,👐🏻,👐🏼,👐🏽,👐🏾,👐🏿 +🤲,🤲,🤲🏻,🤲🏼,🤲🏽,🤲🏾,🤲🏿 +🤜,🤜,🤜🏻,🤜🏼,🤜🏽,🤜🏾,🤜🏿 +🤛,🤛,🤛🏻,🤛🏼,🤛🏽,🤛🏾,🤛🏿 +✊,✊,✊🏻,✊🏼,✊🏽,✊🏾,✊🏿 +👊,👊,👊🏻,👊🏼,👊🏽,👊🏾,👊🏿 +🫳,🫳,🫳🏻,🫳🏼,🫳🏽,🫳🏾,🫳🏿 +🫴,🫴,🫴🏻,🫴🏼,🫴🏽,🫴🏾,🫴🏿 +🫱,🫱,🫱🏻,🫱🏼,🫱🏽,🫱🏾,🫱🏿 +🫲,🫲,🫲🏻,🫲🏼,🫲🏽,🫲🏾,🫲🏿 +🫸,🫸,🫸🏻,🫸🏼,🫸🏽,🫸🏾,🫸🏿 +🫷,🫷,🫷🏻,🫷🏼,🫷🏽,🫷🏾,🫷🏿 +👋,👋,👋🏻,👋🏼,👋🏽,👋🏾,👋🏿 +🤚,🤚,🤚🏻,🤚🏼,🤚🏽,🤚🏾,🤚🏿 +🖐️,🖐️,🖐🏻,🖐🏼,🖐🏽,🖐🏾,🖐🏿 +✋,✋,✋🏻,✋🏼,✋🏽,✋🏾,✋🏿 +🖖,🖖,🖖🏻,🖖🏼,🖖🏽,🖖🏾,🖖🏿 +🤟,🤟,🤟🏻,🤟🏼,🤟🏽,🤟🏾,🤟🏿 +🤘,🤘,🤘🏻,🤘🏼,🤘🏽,🤘🏾,🤘🏿 +✌️,✌️,✌🏻,✌🏼,✌🏽,✌🏾,✌🏿 +🤞,🤞,🤞🏻,🤞🏼,🤞🏽,🤞🏾,🤞🏿 +🫰,🫰,🫰🏻,🫰🏼,🫰🏽,🫰🏾,🫰🏿 +🤙,🤙,🤙🏻,🤙🏼,🤙🏽,🤙🏾,🤙🏿 +🤌,🤌,🤌🏻,🤌🏼,🤌🏽,🤌🏾,🤌🏿 +🤏,🤏,🤏🏻,🤏🏼,🤏🏽,🤏🏾,🤏🏿 +👌,👌,👌🏻,👌🏼,👌🏽,👌🏾,👌🏿 +🫵,🫵,🫵🏻,🫵🏼,🫵🏽,🫵🏾,🫵🏿 +👉,👉,👉🏻,👉🏼,👉🏽,👉🏾,👉🏿 +👈,👈,👈🏻,👈🏼,👈🏽,👈🏾,👈🏿 +☝️,☝️,☝🏻,☝🏼,☝🏽,☝🏾,☝🏿 +👆,👆,👆🏻,👆🏼,👆🏽,👆🏾,👆🏿 +👇,👇,👇🏻,👇🏼,👇🏽,👇🏾,👇🏿 +🖕,🖕,🖕🏻,🖕🏼,🖕🏽,🖕🏾,🖕🏿 +✍️,✍️,✍🏻,✍🏼,✍🏽,✍🏾,✍🏿 +🤳,🤳,🤳🏻,🤳🏼,🤳🏽,🤳🏾,🤳🏿 +🙏,🙏,🙏🏻,🙏🏼,🙏🏽,🙏🏾,🙏🏿 +💅,💅,💅🏻,💅🏼,💅🏽,💅🏾,💅🏿 +🤝,🤝,🤝🏻,🫱🏻‍🫲🏼,🫱🏻‍🫲🏽,🫱🏻‍🫲🏾,🫱🏻‍🫲🏿,🫱🏼‍🫲🏻,🤝🏼,🫱🏼‍🫲🏽,🫱🏼‍🫲🏾,🫱🏼‍🫲🏿,🫱🏽‍🫲🏻,🫱🏽‍🫲🏼,🤝🏽,🫱🏽‍🫲🏾,🫱🏽‍🫲🏿,🫱🏾‍🫲🏻,🫱🏾‍🫲🏼,🫱🏾‍🫲🏽,🤝🏾,🫱🏾‍🫲🏿,🫱🏿‍🫲🏻,🫱🏿‍🫲🏼,🫱🏿‍🫲🏽,🫱🏿‍🫲🏾,🤝🏿 diff --git a/emojipicker/app/src/main/androidx/res/raw/emoji_category_flags.csv b/emojipicker/app/src/main/androidx/res/raw/emoji_category_flags.csv new file mode 100644 index 000000000..c8fd0c064 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/raw/emoji_category_flags.csv @@ -0,0 +1,269 @@ +🏁 +🚩 +🎌 +🏴 +🏳️ +🏳️‍🌈 +🏳️‍⚧️ +🏴‍☠️ +🇦🇨 +🇦🇩 +🇦🇪 +🇦🇫 +🇦🇬 +🇦🇮 +🇦🇱 +🇦🇲 +🇦🇴 +🇦🇶 +🇦🇷 +🇦🇸 +🇦🇹 +🇦🇺 +🇦🇼 +🇦🇽 +🇦🇿 +🇧🇦 +🇧🇧 +🇧🇩 +🇧🇪 +🇧🇫 +🇧🇬 +🇧🇭 +🇧🇮 +🇧🇯 +🇧🇱 +🇧🇲 +🇧🇳 +🇧🇴 +🇧🇶 +🇧🇷 +🇧🇸 +🇧🇹 +🇧🇻 +🇧🇼 +🇧🇾 +🇧🇿 +🇨🇦 +🇨🇨 +🇨🇩 +🇨🇫 +🇨🇬 +🇨🇭 +🇨🇮 +🇨🇰 +🇨🇱 +🇨🇲 +🇨🇳 +🇨🇴 +🇨🇵 +🇨🇷 +🇨🇺 +🇨🇻 +🇨🇼 +🇨🇽 +🇨🇾 +🇨🇿 +🇩🇪 +🇩🇬 +🇩🇯 +🇩🇰 +🇩🇲 +🇩🇴 +🇩🇿 +🇪🇦 +🇪🇨 +🇪🇪 +🇪🇬 +🇪🇭 +🇪🇷 +🇪🇸 +🇪🇹 +🇪🇺 +🇫🇮 +🇫🇯 +🇫🇰 +🇫🇲 +🇫🇴 +🇫🇷 +🇬🇦 +🇬🇧 +🇬🇩 +🇬🇪 +🇬🇫 +🇬🇬 +🇬🇭 +🇬🇮 +🇬🇱 +🇬🇲 +🇬🇳 +🇬🇵 +🇬🇶 +🇬🇷 +🇬🇸 +🇬🇹 +🇬🇺 +🇬🇼 +🇬🇾 +🇭🇰 +🇭🇲 +🇭🇳 +🇭🇷 +🇭🇹 +🇭🇺 +🇮🇨 +🇮🇩 +🇮🇪 +🇮🇱 +🇮🇲 +🇮🇳 +🇮🇴 +🇮🇶 +🇮🇷 +🇮🇸 +🇮🇹 +🇯🇪 +🇯🇲 +🇯🇴 +🇯🇵 +🇰🇪 +🇰🇬 +🇰🇭 +🇰🇮 +🇰🇲 +🇰🇳 +🇰🇵 +🇰🇷 +🇰🇼 +🇰🇾 +🇰🇿 +🇱🇦 +🇱🇧 +🇱🇨 +🇱🇮 +🇱🇰 +🇱🇷 +🇱🇸 +🇱🇹 +🇱🇺 +🇱🇻 +🇱🇾 +🇲🇦 +🇲🇨 +🇲🇩 +🇲🇪 +🇲🇫 +🇲🇬 +🇲🇭 +🇲🇰 +🇲🇱 +🇲🇲 +🇲🇳 +🇲🇴 +🇲🇵 +🇲🇶 +🇲🇷 +🇲🇸 +🇲🇹 +🇲🇺 +🇲🇻 +🇲🇼 +🇲🇽 +🇲🇾 +🇲🇿 +🇳🇦 +🇳🇨 +🇳🇪 +🇳🇫 +🇳🇬 +🇳🇮 +🇳🇱 +🇳🇴 +🇳🇵 +🇳🇷 +🇳🇺 +🇳🇿 +🇴🇲 +🇵🇦 +🇵🇪 +🇵🇫 +🇵🇬 +🇵🇭 +🇵🇰 +🇵🇱 +🇵🇲 +🇵🇳 +🇵🇷 +🇵🇸 +🇵🇹 +🇵🇼 +🇵🇾 +🇶🇦 +🇷🇪 +🇷🇴 +🇷🇸 +🇷🇺 +🇷🇼 +🇸🇦 +🇸🇧 +🇸🇨 +🇸🇩 +🇸🇪 +🇸🇬 +🇸🇭 +🇸🇮 +🇸🇯 +🇸🇰 +🇸🇱 +🇸🇲 +🇸🇳 +🇸🇴 +🇸🇷 +🇸🇸 +🇸🇹 +🇸🇻 +🇸🇽 +🇸🇾 +🇸🇿 +🇹🇦 +🇹🇨 +🇹🇩 +🇹🇫 +🇹🇬 +🇹🇭 +🇹🇯 +🇹🇰 +🇹🇱 +🇹🇲 +🇹🇳 +🇹🇴 +🇹🇷 +🇹🇹 +🇹🇻 +🇹🇼 +🇹🇿 +🇺🇦 +🇺🇬 +🇺🇲 +🇺🇳 +🇺🇸 +🇺🇾 +🇺🇿 +🇻🇦 +🇻🇨 +🇻🇪 +🇻🇬 +🇻🇮 +🇻🇳 +🇻🇺 +🇼🇫 +🇼🇸 +🇽🇰 +🇾🇪 +🇾🇹 +🇿🇦 +🇿🇲 +🇿🇼 +🏴󠁧󠁢󠁥󠁮󠁧󠁿 +🏴󠁧󠁢󠁳󠁣󠁴󠁿 +🏴󠁧󠁢󠁷󠁬󠁳󠁿 diff --git a/emojipicker/app/src/main/androidx/res/raw/emoji_category_food_drink.csv b/emojipicker/app/src/main/androidx/res/raw/emoji_category_food_drink.csv new file mode 100644 index 000000000..8a15f1e42 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/raw/emoji_category_food_drink.csv @@ -0,0 +1,131 @@ +🍓 +🍒 +🍎 +🍉 +🍑 +🍊 +🥭 +🍍 +🍌 +🍋 +🍋‍🟩 +🍈 +🍏 +🍐 +🥝 +🫒 +🫐 +🍇 +🥥 +🍅 +🌶️ +🫚 +🥕 +🧅 +🌽 +🥦 +🥒 +🥬 +🫛 +🫑 +🥑 +🍠 +🍆 +🧄 +🥔 +🍄‍🟫 +🫘 +🌰 +🥜 +🍞 +🫓 +🥐 +🥖 +🥯 +🧇 +🥞 +🍳 +🥚 +🧀 +🥓 +🥩 +🍗 +🍖 +🍔 +🌭 +🥪 +🥨 +🍟 +🍕 +🫔 +🌮 +🌯 +🥙 +🧆 +🥘 +🍝 +🥫 +🫕 +🥣 +🥗 +🍲 +🍛 +🍜 +🦪 +🦞 +🍣 +🍤 +🥡 +🍚 +🍱 +🥟 +🍢 +🍙 +🍘 +🍥 +🍡 +🥠 +🥮 +🍧 +🍨 +🍦 +🥧 +🍰 +🍮 +🎂 +🧁 +🍭 +🍬 +🍫 +🍩 +🍪 +🍯 +🧂 +🧈 +🍿 +🧊 +🫙 +🥤 +🧋 +🧃 +🥛 +🍼 +🍵 +☕ +🫖 +🧉 +🍺 +🍻 +🥂 +🍾 +🍷 +🥃 +🫗 +🍸 +🍹 +🍶 +🥢 +🍴 +🥄 +🔪 +🍽️ diff --git a/emojipicker/app/src/main/androidx/res/raw/emoji_category_objects.csv b/emojipicker/app/src/main/androidx/res/raw/emoji_category_objects.csv new file mode 100644 index 000000000..32c4a4fcd --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/raw/emoji_category_objects.csv @@ -0,0 +1,265 @@ +📱 +☎️ +📞 +📟 +📠 +🔌 +🔋 +🪫 +🖲️ +💽 +💾 +💿 +📀 +🖥️ +💻 +⌨️ +🖨️ +🖱️ +🪙 +💸 +💵 +💴 +💶 +💷 +💳 +💰 +🧾 +🧮 +⚖️ +🛒 +🛍️ +🕯️ +💡 +🔦 +🏮 +🧱 +🪟 +🪞 +🚪 +🪑 +🛏️ +🛋️ +🚿 +🛁 +🚽 +🧻 +🪠 +🧸 +🪆 +🧷 +🪢 +🧹 +🧴 +🧽 +🧼 +🪥 +🪒 +🪮 +🧺 +🧦 +🧤 +🧣 +👖 +👕 +🎽 +👚 +👔 +👗 +👘 +🥻 +🩱 +👙 +🩳 +🩲 +🧥 +🥼 +🦺 +⛑️ +🪖 +🎓 +🎩 +👒 +🧢 +👑 +🪭 +🎒 +👝 +👛 +👜 +💼 +🧳 +☂️ +🌂 +💍 +💎 +💄 +👠 +👟 +👞 +🥿 +🩴 +👡 +👢 +🥾 +🦯 +🕶️ +👓 +🥽 +⚗️ +🧫 +🧪 +🌡️ +💉 +💊 +🩹 +🩺 +🩻 +🧬 +🔭 +🔬 +📡 +🛰️ +🧯 +🪓 +🪜 +🪣 +🪝 +🧲 +🧰 +🗜️ +🔩 +🪛 +🪚 +🔧 +🔨 +⚒️ +🛠️ +⛏️ +⚙️ +⛓️‍💥 +🔗 +⛓️ +📎 +🖇️ +📏 +📐 +🖌️ +🖍️ +🖊️ +🖋️ +✒️ +✏️ +📝 +📖 +📚 +📒 +📔 +📕 +📓 +📗 +📘 +📙 +🔖 +🗒️ +📄 +📃 +📋 +📑 +📂 +📁 +🗂️ +🗃️ +🗄️ +📊 +📈 +📉 +📇 +🪪 +📌 +📍 +✂️ +🗑️ +📰 +🗞️ +🏷️ +📦 +📫 +📪 +📬 +📭 +📮 +✉️ +📧 +📩 +📨 +💌 +📤 +📥 +🗳️ +🕛 +🕧 +🕐 +🕜 +🕑 +🕝 +🕒 +🕞 +🕓 +🕟 +🕔 +🕠 +🕕 +🕡 +🕖 +🕢 +🕗 +🕣 +🕘 +🕤 +🕙 +🕥 +🕚 +🕦 +⏱️ +⌚ +🕰️ +⌛ +⏳ +⏲️ +⏰ +📅 +📆 +🗓️ +🪧 +🛎️ +🔔 +📯 +📢 +📣 +🔈 +🔉 +🔊 +🔍 +🔎 +🔮 +🧿 +🪬 +📿 +🏺 +⚱️ +⚰️ +🪦 +🚬 +💣 +🪤 +📜 +⚔️ +🗡️ +🛡️ +🗝️ +🔑 +🔐 +🔏 +🔒 +🔓 diff --git a/emojipicker/app/src/main/androidx/res/raw/emoji_category_people.csv b/emojipicker/app/src/main/androidx/res/raw/emoji_category_people.csv new file mode 100644 index 000000000..f6e06f6a3 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/raw/emoji_category_people.csv @@ -0,0 +1,151 @@ +🙇,🙇‍♀️,🙇🏻‍♀️,🙇🏼‍♀️,🙇🏽‍♀️,🙇🏾‍♀️,🙇🏿‍♀️,🙇‍♂️,🙇🏻‍♂️,🙇🏼‍♂️,🙇🏽‍♂️,🙇🏾‍♂️,🙇🏿‍♂️ +🙋,🙋‍♀️,🙋🏻‍♀️,🙋🏼‍♀️,🙋🏽‍♀️,🙋🏾‍♀️,🙋🏿‍♀️,🙋‍♂️,🙋🏻‍♂️,🙋🏼‍♂️,🙋🏽‍♂️,🙋🏾‍♂️,🙋🏿‍♂️ +💁,💁‍♀️,💁🏻‍♀️,💁🏼‍♀️,💁🏽‍♀️,💁🏾‍♀️,💁🏿‍♀️,💁‍♂️,💁🏻‍♂️,💁🏼‍♂️,💁🏽‍♂️,💁🏾‍♂️,💁🏿‍♂️ +🙆,🙆‍♀️,🙆🏻‍♀️,🙆🏼‍♀️,🙆🏽‍♀️,🙆🏾‍♀️,🙆🏿‍♀️,🙆‍♂️,🙆🏻‍♂️,🙆🏼‍♂️,🙆🏽‍♂️,🙆🏾‍♂️,🙆🏿‍♂️ +🙅,🙅‍♀️,🙅🏻‍♀️,🙅🏼‍♀️,🙅🏽‍♀️,🙅🏾‍♀️,🙅🏿‍♀️,🙅‍♂️,🙅🏻‍♂️,🙅🏼‍♂️,🙅🏽‍♂️,🙅🏾‍♂️,🙅🏿‍♂️ +🤷,🤷‍♀️,🤷🏻‍♀️,🤷🏼‍♀️,🤷🏽‍♀️,🤷🏾‍♀️,🤷🏿‍♀️,🤷‍♂️,🤷🏻‍♂️,🤷🏼‍♂️,🤷🏽‍♂️,🤷🏾‍♂️,🤷🏿‍♂️ +🤦,🤦‍♀️,🤦🏻‍♀️,🤦🏼‍♀️,🤦🏽‍♀️,🤦🏾‍♀️,🤦🏿‍♀️,🤦‍♂️,🤦🏻‍♂️,🤦🏼‍♂️,🤦🏽‍♂️,🤦🏾‍♂️,🤦🏿‍♂️ +🙍,🙍‍♀️,🙍🏻‍♀️,🙍🏼‍♀️,🙍🏽‍♀️,🙍🏾‍♀️,🙍🏿‍♀️,🙍‍♂️,🙍🏻‍♂️,🙍🏼‍♂️,🙍🏽‍♂️,🙍🏾‍♂️,🙍🏿‍♂️ +🙎,🙎‍♀️,🙎🏻‍♀️,🙎🏼‍♀️,🙎🏽‍♀️,🙎🏾‍♀️,🙎🏿‍♀️,🙎‍♂️,🙎🏻‍♂️,🙎🏼‍♂️,🙎🏽‍♂️,🙎🏾‍♂️,🙎🏿‍♂️ +🧏,🧏‍♀️,🧏🏻‍♀️,🧏🏼‍♀️,🧏🏽‍♀️,🧏🏾‍♀️,🧏🏿‍♀️,🧏‍♂️,🧏🏻‍♂️,🧏🏼‍♂️,🧏🏽‍♂️,🧏🏾‍♂️,🧏🏿‍♂️ +💆,💆‍♀️,💆🏻‍♀️,💆🏼‍♀️,💆🏽‍♀️,💆🏾‍♀️,💆🏿‍♀️,💆‍♂️,💆🏻‍♂️,💆🏼‍♂️,💆🏽‍♂️,💆🏾‍♂️,💆🏿‍♂️ +💇,💇‍♀️,💇🏻‍♀️,💇🏼‍♀️,💇🏽‍♀️,💇🏾‍♀️,💇🏿‍♀️,💇‍♂️,💇🏻‍♂️,💇🏼‍♂️,💇🏽‍♂️,💇🏾‍♂️,💇🏿‍♂️ +🧖,🧖‍♀️,🧖🏻‍♀️,🧖🏼‍♀️,🧖🏽‍♀️,🧖🏾‍♀️,🧖🏿‍♀️,🧖‍♂️,🧖🏻‍♂️,🧖🏼‍♂️,🧖🏽‍♂️,🧖🏾‍♂️,🧖🏿‍♂️ +🛀,🛀,🛀🏻,🛀🏼,🛀🏽,🛀🏾,🛀🏿 +🛌,🛌,🛌🏻,🛌🏼,🛌🏽,🛌🏾,🛌🏿 +🧘,🧘‍♀️,🧘🏻‍♀️,🧘🏼‍♀️,🧘🏽‍♀️,🧘🏾‍♀️,🧘🏿‍♀️,🧘‍♂️,🧘🏻‍♂️,🧘🏼‍♂️,🧘🏽‍♂️,🧘🏾‍♂️,🧘🏿‍♂️ +👨‍🦯,👨‍🦯,👨🏻‍🦯,👨🏼‍🦯,👨🏽‍🦯,👨🏾‍🦯,👨🏿‍🦯 +👩‍🦯,👩‍🦯,👩🏻‍🦯,👩🏼‍🦯,👩🏽‍🦯,👩🏾‍🦯,👩🏿‍🦯 +👨‍🦼,👨‍🦼,👨🏻‍🦼,👨🏼‍🦼,👨🏽‍🦼,👨🏾‍🦼,👨🏿‍🦼 +👩‍🦼,👩‍🦼,👩🏻‍🦼,👩🏼‍🦼,👩🏽‍🦼,👩🏾‍🦼,👩🏿‍🦼 +👨‍🦽,👨‍🦽,👨🏻‍🦽,👨🏼‍🦽,👨🏽‍🦽,👨🏾‍🦽,👨🏿‍🦽 +👩‍🦽,👩‍🦽,👩🏻‍🦽,👩🏼‍🦽,👩🏽‍🦽,👩🏾‍🦽,👩🏿‍🦽 +🧎,🧎‍♀️,🧎🏻‍♀️,🧎🏼‍♀️,🧎🏽‍♀️,🧎🏾‍♀️,🧎🏿‍♀️,🧎‍♂️,🧎🏻‍♂️,🧎🏼‍♂️,🧎🏽‍♂️,🧎🏾‍♂️,🧎🏿‍♂️ +🧍,🧍‍♀️,🧍🏻‍♀️,🧍🏼‍♀️,🧍🏽‍♀️,🧍🏾‍♀️,🧍🏿‍♀️,🧍‍♂️,🧍🏻‍♂️,🧍🏼‍♂️,🧍🏽‍♂️,🧍🏾‍♂️,🧍🏿‍♂️ +🚶,🚶‍♀️,🚶🏻‍♀️,🚶🏼‍♀️,🚶🏽‍♀️,🚶🏾‍♀️,🚶🏿‍♀️,🚶‍♂️,🚶🏻‍♂️,🚶🏼‍♂️,🚶🏽‍♂️,🚶🏾‍♂️,🚶🏿‍♂️ +🏃,🏃‍♀️,🏃🏻‍♀️,🏃🏼‍♀️,🏃🏽‍♀️,🏃🏾‍♀️,🏃🏿‍♀️,🏃‍♂️,🏃🏻‍♂️,🏃🏼‍♂️,🏃🏽‍♂️,🏃🏾‍♂️,🏃🏿‍♂️ +🤸,🤸‍♀️,🤸🏻‍♀️,🤸🏼‍♀️,🤸🏽‍♀️,🤸🏾‍♀️,🤸🏿‍♀️,🤸‍♂️,🤸🏻‍♂️,🤸🏼‍♂️,🤸🏽‍♂️,🤸🏾‍♂️,🤸🏿‍♂️ +🏋️,🏋️‍♀️,🏋🏻‍♀️,🏋🏼‍♀️,🏋🏽‍♀️,🏋🏾‍♀️,🏋🏿‍♀️,🏋️‍♂️,🏋🏻‍♂️,🏋🏼‍♂️,🏋🏽‍♂️,🏋🏾‍♂️,🏋🏿‍♂️ +⛹️,⛹️‍♀️,⛹🏻‍♀️,⛹🏼‍♀️,⛹🏽‍♀️,⛹🏾‍♀️,⛹🏿‍♀️,⛹️‍♂️,⛹🏻‍♂️,⛹🏼‍♂️,⛹🏽‍♂️,⛹🏾‍♂️,⛹🏿‍♂️ +🤾,🤾‍♀️,🤾🏻‍♀️,🤾🏼‍♀️,🤾🏽‍♀️,🤾🏾‍♀️,🤾🏿‍♀️,🤾‍♂️,🤾🏻‍♂️,🤾🏼‍♂️,🤾🏽‍♂️,🤾🏾‍♂️,🤾🏿‍♂️ +🚴,🚴‍♀️,🚴🏻‍♀️,🚴🏼‍♀️,🚴🏽‍♀️,🚴🏾‍♀️,🚴🏿‍♀️,🚴‍♂️,🚴🏻‍♂️,🚴🏼‍♂️,🚴🏽‍♂️,🚴🏾‍♂️,🚴🏿‍♂️ +🚵,🚵‍♀️,🚵🏻‍♀️,🚵🏼‍♀️,🚵🏽‍♀️,🚵🏾‍♀️,🚵🏿‍♀️,🚵‍♂️,🚵🏻‍♂️,🚵🏼‍♂️,🚵🏽‍♂️,🚵🏾‍♂️,🚵🏿‍♂️ +🧗,🧗‍♀️,🧗🏻‍♀️,🧗🏼‍♀️,🧗🏽‍♀️,🧗🏾‍♀️,🧗🏿‍♀️,🧗‍♂️,🧗🏻‍♂️,🧗🏼‍♂️,🧗🏽‍♂️,🧗🏾‍♂️,🧗🏿‍♂️ +🤼,🤼‍♀️,🤼‍♂️ +🤹,🤹‍♀️,🤹🏻‍♀️,🤹🏼‍♀️,🤹🏽‍♀️,🤹🏾‍♀️,🤹🏿‍♀️,🤹‍♂️,🤹🏻‍♂️,🤹🏼‍♂️,🤹🏽‍♂️,🤹🏾‍♂️,🤹🏿‍♂️ +🏌️,🏌️‍♀️,🏌🏻‍♀️,🏌🏼‍♀️,🏌🏽‍♀️,🏌🏾‍♀️,🏌🏿‍♀️,🏌️‍♂️,🏌🏻‍♂️,🏌🏼‍♂️,🏌🏽‍♂️,🏌🏾‍♂️,🏌🏿‍♂️ +🏇,🏇,🏇🏻,🏇🏼,🏇🏽,🏇🏾,🏇🏿 +🤺 +⛷️ +🏂,🏂,🏂🏻,🏂🏼,🏂🏽,🏂🏾,🏂🏿 +🪂 +🏄,🏄‍♀️,🏄🏻‍♀️,🏄🏼‍♀️,🏄🏽‍♀️,🏄🏾‍♀️,🏄🏿‍♀️,🏄‍♂️,🏄🏻‍♂️,🏄🏼‍♂️,🏄🏽‍♂️,🏄🏾‍♂️,🏄🏿‍♂️ +🚣,🚣‍♀️,🚣🏻‍♀️,🚣🏼‍♀️,🚣🏽‍♀️,🚣🏾‍♀️,🚣🏿‍♀️,🚣‍♂️,🚣🏻‍♂️,🚣🏼‍♂️,🚣🏽‍♂️,🚣🏾‍♂️,🚣🏿‍♂️ +🏊,🏊‍♀️,🏊🏻‍♀️,🏊🏼‍♀️,🏊🏽‍♀️,🏊🏾‍♀️,🏊🏿‍♀️,🏊‍♂️,🏊🏻‍♂️,🏊🏼‍♂️,🏊🏽‍♂️,🏊🏾‍♂️,🏊🏿‍♂️ +🤽,🤽‍♀️,🤽🏻‍♀️,🤽🏼‍♀️,🤽🏽‍♀️,🤽🏾‍♀️,🤽🏿‍♀️,🤽‍♂️,🤽🏻‍♂️,🤽🏼‍♂️,🤽🏽‍♂️,🤽🏾‍♂️,🤽🏿‍♂️ +🧜,🧜‍♀️,🧜🏻‍♀️,🧜🏼‍♀️,🧜🏽‍♀️,🧜🏾‍♀️,🧜🏿‍♀️,🧜‍♂️,🧜🏻‍♂️,🧜🏼‍♂️,🧜🏽‍♂️,🧜🏾‍♂️,🧜🏿‍♂️ +🧚,🧚‍♀️,🧚🏻‍♀️,🧚🏼‍♀️,🧚🏽‍♀️,🧚🏾‍♀️,🧚🏿‍♀️,🧚‍♂️,🧚🏻‍♂️,🧚🏼‍♂️,🧚🏽‍♂️,🧚🏾‍♂️,🧚🏿‍♂️ +🧞,🧞‍♀️,🧞‍♂️ +🦸,🦸‍♀️,🦸🏻‍♀️,🦸🏼‍♀️,🦸🏽‍♀️,🦸🏾‍♀️,🦸🏿‍♀️,🦸‍♂️,🦸🏻‍♂️,🦸🏼‍♂️,🦸🏽‍♂️,🦸🏾‍♂️,🦸🏿‍♂️ +🦹,🦹‍♀️,🦹🏻‍♀️,🦹🏼‍♀️,🦹🏽‍♀️,🦹🏾‍♀️,🦹🏿‍♀️,🦹‍♂️,🦹🏻‍♂️,🦹🏼‍♂️,🦹🏽‍♂️,🦹🏾‍♂️,🦹🏿‍♂️ +🧝,🧝‍♀️,🧝🏻‍♀️,🧝🏼‍♀️,🧝🏽‍♀️,🧝🏾‍♀️,🧝🏿‍♀️,🧝‍♂️,🧝🏻‍♂️,🧝🏼‍♂️,🧝🏽‍♂️,🧝🏾‍♂️,🧝🏿‍♂️ +🧙,🧙‍♀️,🧙🏻‍♀️,🧙🏼‍♀️,🧙🏽‍♀️,🧙🏾‍♀️,🧙🏿‍♀️,🧙‍♂️,🧙🏻‍♂️,🧙🏼‍♂️,🧙🏽‍♂️,🧙🏾‍♂️,🧙🏿‍♂️ +🧟,🧟‍♀️,🧟‍♂️ +🧛,🧛‍♀️,🧛🏻‍♀️,🧛🏼‍♀️,🧛🏽‍♀️,🧛🏾‍♀️,🧛🏿‍♀️,🧛‍♂️,🧛🏻‍♂️,🧛🏼‍♂️,🧛🏽‍♂️,🧛🏾‍♂️,🧛🏿‍♂️ +👼,👼,👼🏻,👼🏼,👼🏽,👼🏾,👼🏿 +🎅,🎅,🎅🏻,🎅🏼,🎅🏽,🎅🏾,🎅🏿 +🤶,🤶,🤶🏻,🤶🏼,🤶🏽,🤶🏾,🤶🏿 +💂,💂‍♀️,💂🏻‍♀️,💂🏼‍♀️,💂🏽‍♀️,💂🏾‍♀️,💂🏿‍♀️,💂‍♂️,💂🏻‍♂️,💂🏼‍♂️,💂🏽‍♂️,💂🏾‍♂️,💂🏿‍♂️ +🤴,🤴,🤴🏻,🤴🏼,🤴🏽,🤴🏾,🤴🏿 +👸,👸,👸🏻,👸🏼,👸🏽,👸🏾,👸🏿 +🤵,🤵,🤵🏻,🤵🏼,🤵🏽,🤵🏾,🤵🏿 +👰,👰,👰🏻,👰🏼,👰🏽,👰🏾,👰🏿 +👩‍🚀,👨‍🚀,👨🏻‍🚀,👨🏼‍🚀,👨🏽‍🚀,👨🏾‍🚀,👨🏿‍🚀,👩‍🚀,👩🏻‍🚀,👩🏼‍🚀,👩🏽‍🚀,👩🏾‍🚀,👩🏿‍🚀 +👷,👷‍♀️,👷🏻‍♀️,👷🏼‍♀️,👷🏽‍♀️,👷🏾‍♀️,👷🏿‍♀️,👷‍♂️,👷🏻‍♂️,👷🏼‍♂️,👷🏽‍♂️,👷🏾‍♂️,👷🏿‍♂️ +👮,👮‍♀️,👮🏻‍♀️,👮🏼‍♀️,👮🏽‍♀️,👮🏾‍♀️,👮🏿‍♀️,👮‍♂️,👮🏻‍♂️,👮🏼‍♂️,👮🏽‍♂️,👮🏾‍♂️,👮🏿‍♂️ +🕵️,🕵️‍♀️,🕵🏻‍♀️,🕵🏼‍♀️,🕵🏽‍♀️,🕵🏾‍♀️,🕵🏿‍♀️,🕵️‍♂️,🕵🏻‍♂️,🕵🏼‍♂️,🕵🏽‍♂️,🕵🏾‍♂️,🕵🏿‍♂️ +👩‍✈️,👨‍✈️,👨🏻‍✈️,👨🏼‍✈️,👨🏽‍✈️,👨🏾‍✈️,👨🏿‍✈️,👩‍✈️,👩🏻‍✈️,👩🏼‍✈️,👩🏽‍✈️,👩🏾‍✈️,👩🏿‍✈️ +👩‍🔬,👨‍🔬,👨🏻‍🔬,👨🏼‍🔬,👨🏽‍🔬,👨🏾‍🔬,👨🏿‍🔬,👩‍🔬,👩🏻‍🔬,👩🏼‍🔬,👩🏽‍🔬,👩🏾‍🔬,👩🏿‍🔬 +👩‍⚕️,👨‍⚕️,👨🏻‍⚕️,👨🏼‍⚕️,👨🏽‍⚕️,👨🏾‍⚕️,👨🏿‍⚕️,👩‍⚕️,👩🏻‍⚕️,👩🏼‍⚕️,👩🏽‍⚕️,👩🏾‍⚕️,👩🏿‍⚕️ +👩‍🔧,👨‍🔧,👨🏻‍🔧,👨🏼‍🔧,👨🏽‍🔧,👨🏾‍🔧,👨🏿‍🔧,👩‍🔧,👩🏻‍🔧,👩🏼‍🔧,👩🏽‍🔧,👩🏾‍🔧,👩🏿‍🔧 +👩‍🏭,👨‍🏭,👨🏻‍🏭,👨🏼‍🏭,👨🏽‍🏭,👨🏾‍🏭,👨🏿‍🏭,👩‍🏭,👩🏻‍🏭,👩🏼‍🏭,👩🏽‍🏭,👩🏾‍🏭,👩🏿‍🏭 +👩‍🚒,👨‍🚒,👨🏻‍🚒,👨🏼‍🚒,👨🏽‍🚒,👨🏾‍🚒,👨🏿‍🚒,👩‍🚒,👩🏻‍🚒,👩🏼‍🚒,👩🏽‍🚒,👩🏾‍🚒,👩🏿‍🚒 +👩‍🌾,👨‍🌾,👨🏻‍🌾,👨🏼‍🌾,👨🏽‍🌾,👨🏾‍🌾,👨🏿‍🌾,👩‍🌾,👩🏻‍🌾,👩🏼‍🌾,👩🏽‍🌾,👩🏾‍🌾,👩🏿‍🌾 +👩‍🏫,👨‍🏫,👨🏻‍🏫,👨🏼‍🏫,👨🏽‍🏫,👨🏾‍🏫,👨🏿‍🏫,👩‍🏫,👩🏻‍🏫,👩🏼‍🏫,👩🏽‍🏫,👩🏾‍🏫,👩🏿‍🏫 +👩‍🎓,👨‍🎓,👨🏻‍🎓,👨🏼‍🎓,👨🏽‍🎓,👨🏾‍🎓,👨🏿‍🎓,👩‍🎓,👩🏻‍🎓,👩🏼‍🎓,👩🏽‍🎓,👩🏾‍🎓,👩🏿‍🎓 +👩‍💼,👨‍💼,👨🏻‍💼,👨🏼‍💼,👨🏽‍💼,👨🏾‍💼,👨🏿‍💼,👩‍💼,👩🏻‍💼,👩🏼‍💼,👩🏽‍💼,👩🏾‍💼,👩🏿‍💼 +👩‍⚖️,👨‍⚖️,👨🏻‍⚖️,👨🏼‍⚖️,👨🏽‍⚖️,👨🏾‍⚖️,👨🏿‍⚖️,👩‍⚖️,👩🏻‍⚖️,👩🏼‍⚖️,👩🏽‍⚖️,👩🏾‍⚖️,👩🏿‍⚖️ +👩‍💻,👨‍💻,👨🏻‍💻,👨🏼‍💻,👨🏽‍💻,👨🏾‍💻,👨🏿‍💻,👩‍💻,👩🏻‍💻,👩🏼‍💻,👩🏽‍💻,👩🏾‍💻,👩🏿‍💻 +👩‍🎤,👨‍🎤,👨🏻‍🎤,👨🏼‍🎤,👨🏽‍🎤,👨🏾‍🎤,👨🏿‍🎤,👩‍🎤,👩🏻‍🎤,👩🏼‍🎤,👩🏽‍🎤,👩🏾‍🎤,👩🏿‍🎤 +👩‍🎨,👨‍🎨,👨🏻‍🎨,👨🏼‍🎨,👨🏽‍🎨,👨🏾‍🎨,👨🏿‍🎨,👩‍🎨,👩🏻‍🎨,👩🏼‍🎨,👩🏽‍🎨,👩🏾‍🎨,👩🏿‍🎨 +👩‍🍳,👨‍🍳,👨🏻‍🍳,👨🏼‍🍳,👨🏽‍🍳,👨🏾‍🍳,👨🏿‍🍳,👩‍🍳,👩🏻‍🍳,👩🏼‍🍳,👩🏽‍🍳,👩🏾‍🍳,👩🏿‍🍳 +👳,👳‍♀️,👳🏻‍♀️,👳🏼‍♀️,👳🏽‍♀️,👳🏾‍♀️,👳🏿‍♀️,👳‍♂️,👳🏻‍♂️,👳🏼‍♂️,👳🏽‍♂️,👳🏾‍♂️,👳🏿‍♂️ +🧕,🧕,🧕🏻,🧕🏼,🧕🏽,🧕🏾,🧕🏿 +👲,👲,👲🏻,👲🏼,👲🏽,👲🏾,👲🏿 +👶,👶,👶🏻,👶🏼,👶🏽,👶🏾,👶🏿 +🧒,🧒,🧒🏻,🧒🏼,🧒🏽,🧒🏾,🧒🏿 +👦,👦,👦🏻,👦🏼,👦🏽,👦🏾,👦🏿 +👧,👧,👧🏻,👧🏼,👧🏽,👧🏾,👧🏿 +🧑,🧑,🧑🏻,🧑🏼,🧑🏽,🧑🏾,🧑🏿 +👨,👨,👨🏻,👨🏼,👨🏽,👨🏾,👨🏿 +👩,👩,👩🏻,👩🏼,👩🏽,👩🏾,👩🏿 +🧓,🧓,🧓🏻,🧓🏼,🧓🏽,🧓🏾,🧓🏿 +👴,👴,👴🏻,👴🏼,👴🏽,👴🏾,👴🏿 +👵,👵,👵🏻,👵🏼,👵🏽,👵🏾,👵🏿 +👨‍🦳,👨‍🦳,👨🏻‍🦳,👨🏼‍🦳,👨🏽‍🦳,👨🏾‍🦳,👨🏿‍🦳 +👩‍🦳,👩‍🦳,👩🏻‍🦳,👩🏼‍🦳,👩🏽‍🦳,👩🏾‍🦳,👩🏿‍🦳 +👨‍🦰,👨‍🦰,👨🏻‍🦰,👨🏼‍🦰,👨🏽‍🦰,👨🏾‍🦰,👨🏿‍🦰 +👩‍🦰,👩‍🦰,👩🏻‍🦰,👩🏼‍🦰,👩🏽‍🦰,👩🏾‍🦰,👩🏿‍🦰 +👱,👱‍♀️,👱🏻‍♀️,👱🏼‍♀️,👱🏽‍♀️,👱🏾‍♀️,👱🏿‍♀️,👱‍♂️,👱🏻‍♂️,👱🏼‍♂️,👱🏽‍♂️,👱🏾‍♂️,👱🏿‍♂️ +👨‍🦱,👨‍🦱,👨🏻‍🦱,👨🏼‍🦱,👨🏽‍🦱,👨🏾‍🦱,👨🏿‍🦱 +👩‍🦱,👩‍🦱,👩🏻‍🦱,👩🏼‍🦱,👩🏽‍🦱,👩🏾‍🦱,👩🏿‍🦱 +👨‍🦲,👨‍🦲,👨🏻‍🦲,👨🏼‍🦲,👨🏽‍🦲,👨🏾‍🦲,👨🏿‍🦲 +👩‍🦲,👩‍🦲,👩🏻‍🦲,👩🏼‍🦲,👩🏽‍🦲,👩🏾‍🦲,👩🏿‍🦲 +🧔,🧔,🧔🏻,🧔🏼,🧔🏽,🧔🏾,🧔🏿 +🕴️,🕴️,🕴🏻,🕴🏼,🕴🏽,🕴🏾,🕴🏿 +💃,💃,💃🏻,💃🏼,💃🏽,💃🏾,💃🏿 +🕺,🕺,🕺🏻,🕺🏼,🕺🏽,🕺🏾,🕺🏿 +👯,👯‍♀️,👯‍♂️ +👭 +👫 +👬 +💏 +👩‍❤️‍💋‍👨 +👨‍❤️‍💋‍👨 +👩‍❤️‍💋‍👩 +💑 +👩‍❤️‍👨 +👨‍❤️‍👨 +👩‍❤️‍👩 +👪 +👨‍👩‍👦 +👨‍👩‍👧 +👨‍👩‍👧‍👦 +👨‍👩‍👦‍👦 +👨‍👩‍👧‍👧 +👨‍👨‍👦 +👨‍👨‍👧 +👨‍👨‍👧‍👦 +👨‍👨‍👦‍👦 +👨‍👨‍👧‍👧 +👩‍👩‍👦 +👩‍👩‍👧 +👩‍👩‍👧‍👦 +👩‍👩‍👦‍👦 +👩‍👩‍👧‍👧 +👨‍👦 +👨‍👦‍👦 +👨‍👧 +👨‍👧‍👦 +👨‍👧‍👧 +👩‍👦 +👩‍👦‍👦 +👩‍👧 +👩‍👧‍👦 +👩‍👧‍👧 +🤰,🤰,🤰🏻,🤰🏼,🤰🏽,🤰🏾,🤰🏿 +🤱,🤱,🤱🏻,🤱🏼,🤱🏽,🤱🏾,🤱🏿 +🗣️ +👤 +👥 +👣 diff --git a/emojipicker/app/src/main/androidx/res/raw/emoji_category_people_gender_inclusive.csv b/emojipicker/app/src/main/androidx/res/raw/emoji_category_people_gender_inclusive.csv new file mode 100644 index 000000000..ec86a370b --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/raw/emoji_category_people_gender_inclusive.csv @@ -0,0 +1,110 @@ +🙇,🙇,🙇🏻,🙇🏼,🙇🏽,🙇🏾,🙇🏿,🙇‍♀️,🙇🏻‍♀️,🙇🏼‍♀️,🙇🏽‍♀️,🙇🏾‍♀️,🙇🏿‍♀️,🙇‍♂️,🙇🏻‍♂️,🙇🏼‍♂️,🙇🏽‍♂️,🙇🏾‍♂️,🙇🏿‍♂️ +🙋,🙋,🙋🏻,🙋🏼,🙋🏽,🙋🏾,🙋🏿,🙋‍♀️,🙋🏻‍♀️,🙋🏼‍♀️,🙋🏽‍♀️,🙋🏾‍♀️,🙋🏿‍♀️,🙋‍♂️,🙋🏻‍♂️,🙋🏼‍♂️,🙋🏽‍♂️,🙋🏾‍♂️,🙋🏿‍♂️ +💁,💁,💁🏻,💁🏼,💁🏽,💁🏾,💁🏿,💁‍♀️,💁🏻‍♀️,💁🏼‍♀️,💁🏽‍♀️,💁🏾‍♀️,💁🏿‍♀️,💁‍♂️,💁🏻‍♂️,💁🏼‍♂️,💁🏽‍♂️,💁🏾‍♂️,💁🏿‍♂️ +🙆,🙆,🙆🏻,🙆🏼,🙆🏽,🙆🏾,🙆🏿,🙆‍♀️,🙆🏻‍♀️,🙆🏼‍♀️,🙆🏽‍♀️,🙆🏾‍♀️,🙆🏿‍♀️,🙆‍♂️,🙆🏻‍♂️,🙆🏼‍♂️,🙆🏽‍♂️,🙆🏾‍♂️,🙆🏿‍♂️ +🙅,🙅,🙅🏻,🙅🏼,🙅🏽,🙅🏾,🙅🏿,🙅‍♀️,🙅🏻‍♀️,🙅🏼‍♀️,🙅🏽‍♀️,🙅🏾‍♀️,🙅🏿‍♀️,🙅‍♂️,🙅🏻‍♂️,🙅🏼‍♂️,🙅🏽‍♂️,🙅🏾‍♂️,🙅🏿‍♂️ +🤷,🤷,🤷🏻,🤷🏼,🤷🏽,🤷🏾,🤷🏿,🤷‍♀️,🤷🏻‍♀️,🤷🏼‍♀️,🤷🏽‍♀️,🤷🏾‍♀️,🤷🏿‍♀️,🤷‍♂️,🤷🏻‍♂️,🤷🏼‍♂️,🤷🏽‍♂️,🤷🏾‍♂️,🤷🏿‍♂️ +🤦,🤦,🤦🏻,🤦🏼,🤦🏽,🤦🏾,🤦🏿,🤦‍♀️,🤦🏻‍♀️,🤦🏼‍♀️,🤦🏽‍♀️,🤦🏾‍♀️,🤦🏿‍♀️,🤦‍♂️,🤦🏻‍♂️,🤦🏼‍♂️,🤦🏽‍♂️,🤦🏾‍♂️,🤦🏿‍♂️ +🙍,🙍,🙍🏻,🙍🏼,🙍🏽,🙍🏾,🙍🏿,🙍‍♀️,🙍🏻‍♀️,🙍🏼‍♀️,🙍🏽‍♀️,🙍🏾‍♀️,🙍🏿‍♀️,🙍‍♂️,🙍🏻‍♂️,🙍🏼‍♂️,🙍🏽‍♂️,🙍🏾‍♂️,🙍🏿‍♂️ +🙎,🙎,🙎🏻,🙎🏼,🙎🏽,🙎🏾,🙎🏿,🙎‍♀️,🙎🏻‍♀️,🙎🏼‍♀️,🙎🏽‍♀️,🙎🏾‍♀️,🙎🏿‍♀️,🙎‍♂️,🙎🏻‍♂️,🙎🏼‍♂️,🙎🏽‍♂️,🙎🏾‍♂️,🙎🏿‍♂️ +🧏,🧏,🧏🏻,🧏🏼,🧏🏽,🧏🏾,🧏🏿,🧏‍♀️,🧏🏻‍♀️,🧏🏼‍♀️,🧏🏽‍♀️,🧏🏾‍♀️,🧏🏿‍♀️,🧏‍♂️,🧏🏻‍♂️,🧏🏼‍♂️,🧏🏽‍♂️,🧏🏾‍♂️,🧏🏿‍♂️ +💆,💆,💆🏻,💆🏼,💆🏽,💆🏾,💆🏿,💆‍♀️,💆🏻‍♀️,💆🏼‍♀️,💆🏽‍♀️,💆🏾‍♀️,💆🏿‍♀️,💆‍♂️,💆🏻‍♂️,💆🏼‍♂️,💆🏽‍♂️,💆🏾‍♂️,💆🏿‍♂️ +💇,💇,💇🏻,💇🏼,💇🏽,💇🏾,💇🏿,💇‍♀️,💇🏻‍♀️,💇🏼‍♀️,💇🏽‍♀️,💇🏾‍♀️,💇🏿‍♀️,💇‍♂️,💇🏻‍♂️,💇🏼‍♂️,💇🏽‍♂️,💇🏾‍♂️,💇🏿‍♂️ +🧖,🧖,🧖🏻,🧖🏼,🧖🏽,🧖🏾,🧖🏿,🧖‍♀️,🧖🏻‍♀️,🧖🏼‍♀️,🧖🏽‍♀️,🧖🏾‍♀️,🧖🏿‍♀️,🧖‍♂️,🧖🏻‍♂️,🧖🏼‍♂️,🧖🏽‍♂️,🧖🏾‍♂️,🧖🏿‍♂️ +🛀,🛀,🛀🏻,🛀🏼,🛀🏽,🛀🏾,🛀🏿 +🛌,🛌,🛌🏻,🛌🏼,🛌🏽,🛌🏾,🛌🏿 +🧘,🧘,🧘🏻,🧘🏼,🧘🏽,🧘🏾,🧘🏿,🧘‍♀️,🧘🏻‍♀️,🧘🏼‍♀️,🧘🏽‍♀️,🧘🏾‍♀️,🧘🏿‍♀️,🧘‍♂️,🧘🏻‍♂️,🧘🏼‍♂️,🧘🏽‍♂️,🧘🏾‍♂️,🧘🏿‍♂️ +🧍,🧍,🧍🏻,🧍🏼,🧍🏽,🧍🏾,🧍🏿,🧍‍♀️,🧍🏻‍♀️,🧍🏼‍♀️,🧍🏽‍♀️,🧍🏾‍♀️,🧍🏿‍♀️,🧍‍♂️,🧍🏻‍♂️,🧍🏼‍♂️,🧍🏽‍♂️,🧍🏾‍♂️,🧍🏿‍♂️ +🤸,🤸,🤸🏻,🤸🏼,🤸🏽,🤸🏾,🤸🏿,🤸‍♀️,🤸🏻‍♀️,🤸🏼‍♀️,🤸🏽‍♀️,🤸🏾‍♀️,🤸🏿‍♀️,🤸‍♂️,🤸🏻‍♂️,🤸🏼‍♂️,🤸🏽‍♂️,🤸🏾‍♂️,🤸🏿‍♂️ +🧎,🧎,🧎🏻,🧎🏼,🧎🏽,🧎🏾,🧎🏿,🧎‍➡️,🧎🏻‍➡️,🧎🏼‍➡️,🧎🏽‍➡️,🧎🏾‍➡️,🧎🏿‍➡️,🧎‍♀️,🧎🏻‍♀️,🧎🏼‍♀️,🧎🏽‍♀️,🧎🏾‍♀️,🧎🏿‍♀️,🧎‍♀️‍➡️,🧎🏻‍♀️‍➡️,🧎🏼‍♀️‍➡️,🧎🏽‍♀️‍➡️,🧎🏾‍♀️‍➡️,🧎🏿‍♀️‍➡️,🧎‍♂️,🧎🏻‍♂️,🧎🏼‍♂️,🧎🏽‍♂️,🧎🏾‍♂️,🧎🏿‍♂️,🧎‍♂️‍➡️,🧎🏻‍♂️‍➡️,🧎🏼‍♂️‍➡️,🧎🏽‍♂️‍➡️,🧎🏾‍♂️‍➡️,🧎🏿‍♂️‍➡️ +🧑‍🦼,🧑‍🦼,🧑🏻‍🦼,🧑🏼‍🦼,🧑🏽‍🦼,🧑🏾‍🦼,🧑🏿‍🦼,🧑‍🦼‍➡️,🧑🏻‍🦼‍➡️,🧑🏼‍🦼‍➡️,🧑🏽‍🦼‍➡️,🧑🏾‍🦼‍➡️,🧑🏿‍🦼‍➡️,👩‍🦼,👩🏻‍🦼,👩🏼‍🦼,👩🏽‍🦼,👩🏾‍🦼,👩🏿‍🦼,👩‍🦼‍➡️,👩🏻‍🦼‍➡️,👩🏼‍🦼‍➡️,👩🏽‍🦼‍➡️,👩🏾‍🦼‍➡️,👩🏿‍🦼‍➡️,👨‍🦼,👨🏻‍🦼,👨🏼‍🦼,👨🏽‍🦼,👨🏾‍🦼,👨🏿‍🦼,👨‍🦼‍➡️,👨🏻‍🦼‍➡️,👨🏼‍🦼‍➡️,👨🏽‍🦼‍➡️,👨🏾‍🦼‍➡️,👨🏿‍🦼‍➡️ +🧑‍🦽,🧑‍🦽,🧑🏻‍🦽,🧑🏼‍🦽,🧑🏽‍🦽,🧑🏾‍🦽,🧑🏿‍🦽,🧑‍🦽‍➡️,🧑🏻‍🦽‍➡️,🧑🏼‍🦽‍➡️,🧑🏽‍🦽‍➡️,🧑🏾‍🦽‍➡️,🧑🏿‍🦽‍➡️,👩‍🦽,👩🏻‍🦽,👩🏼‍🦽,👩🏽‍🦽,👩🏾‍🦽,👩🏿‍🦽,👩‍🦽‍➡️,👩🏻‍🦽‍➡️,👩🏼‍🦽‍➡️,👩🏽‍🦽‍➡️,👩🏾‍🦽‍➡️,👩🏿‍🦽‍➡️,👨‍🦽,👨🏻‍🦽,👨🏼‍🦽,👨🏽‍🦽,👨🏾‍🦽,👨🏿‍🦽,👨‍🦽‍➡️,👨🏻‍🦽‍➡️,👨🏼‍🦽‍➡️,👨🏽‍🦽‍➡️,👨🏾‍🦽‍➡️,👨🏿‍🦽‍➡️ +🧑‍🦯,🧑‍🦯,🧑🏻‍🦯,🧑🏼‍🦯,🧑🏽‍🦯,🧑🏾‍🦯,🧑🏿‍🦯,🧑‍🦯‍➡️,🧑🏻‍🦯‍➡️,🧑🏼‍🦯‍➡️,🧑🏽‍🦯‍➡️,🧑🏾‍🦯‍➡️,🧑🏿‍🦯‍➡️,👩‍🦯,👩🏻‍🦯,👩🏼‍🦯,👩🏽‍🦯,👩🏾‍🦯,👩🏿‍🦯,👩‍🦯‍➡️,👩🏻‍🦯‍➡️,👩🏼‍🦯‍➡️,👩🏽‍🦯‍➡️,👩🏾‍🦯‍➡️,👩🏿‍🦯‍➡️,👨‍🦯,👨🏻‍🦯,👨🏼‍🦯,👨🏽‍🦯,👨🏾‍🦯,👨🏿‍🦯,👨‍🦯‍➡️,👨🏻‍🦯‍➡️,👨🏼‍🦯‍➡️,👨🏽‍🦯‍➡️,👨🏾‍🦯‍➡️,👨🏿‍🦯‍➡️ +🚶,🚶,🚶🏻,🚶🏼,🚶🏽,🚶🏾,🚶🏿,🚶‍➡️,🚶🏻‍➡️,🚶🏼‍➡️,🚶🏽‍➡️,🚶🏾‍➡️,🚶🏿‍➡️,🚶‍♀️,🚶🏻‍♀️,🚶🏼‍♀️,🚶🏽‍♀️,🚶🏾‍♀️,🚶🏿‍♀️,🚶‍♀️‍➡️,🚶🏻‍♀️‍➡️,🚶🏼‍♀️‍➡️,🚶🏽‍♀️‍➡️,🚶🏾‍♀️‍➡️,🚶🏿‍♀️‍➡️,🚶‍♂️,🚶🏻‍♂️,🚶🏼‍♂️,🚶🏽‍♂️,🚶🏾‍♂️,🚶🏿‍♂️,🚶‍♂️‍➡️,🚶🏻‍♂️‍➡️,🚶🏼‍♂️‍➡️,🚶🏽‍♂️‍➡️,🚶🏾‍♂️‍➡️,🚶🏿‍♂️‍➡️ +🏃,🏃,🏃🏻,🏃🏼,🏃🏽,🏃🏾,🏃🏿,🏃‍➡️,🏃🏻‍➡️,🏃🏼‍➡️,🏃🏽‍➡️,🏃🏾‍➡️,🏃🏿‍➡️,🏃‍♀️,🏃🏻‍♀️,🏃🏼‍♀️,🏃🏽‍♀️,🏃🏾‍♀️,🏃🏿‍♀️,🏃‍♀️‍➡️,🏃🏻‍♀️‍➡️,🏃🏼‍♀️‍➡️,🏃🏽‍♀️‍➡️,🏃🏾‍♀️‍➡️,🏃🏿‍♀️‍➡️,🏃‍♂️,🏃🏻‍♂️,🏃🏼‍♂️,🏃🏽‍♂️,🏃🏾‍♂️,🏃🏿‍♂️,🏃‍♂️‍➡️,🏃🏻‍♂️‍➡️,🏃🏼‍♂️‍➡️,🏃🏽‍♂️‍➡️,🏃🏾‍♂️‍➡️,🏃🏿‍♂️‍➡️ +⛹️,⛹️,⛹🏻,⛹🏼,⛹🏽,⛹🏾,⛹🏿,⛹️‍♀️,⛹🏻‍♀️,⛹🏼‍♀️,⛹🏽‍♀️,⛹🏾‍♀️,⛹🏿‍♀️,⛹️‍♂️,⛹🏻‍♂️,⛹🏼‍♂️,⛹🏽‍♂️,⛹🏾‍♂️,⛹🏿‍♂️ +🤾,🤾,🤾🏻,🤾🏼,🤾🏽,🤾🏾,🤾🏿,🤾‍♀️,🤾🏻‍♀️,🤾🏼‍♀️,🤾🏽‍♀️,🤾🏾‍♀️,🤾🏿‍♀️,🤾‍♂️,🤾🏻‍♂️,🤾🏼‍♂️,🤾🏽‍♂️,🤾🏾‍♂️,🤾🏿‍♂️ +🚴,🚴,🚴🏻,🚴🏼,🚴🏽,🚴🏾,🚴🏿,🚴‍♀️,🚴🏻‍♀️,🚴🏼‍♀️,🚴🏽‍♀️,🚴🏾‍♀️,🚴🏿‍♀️,🚴‍♂️,🚴🏻‍♂️,🚴🏼‍♂️,🚴🏽‍♂️,🚴🏾‍♂️,🚴🏿‍♂️ +🚵,🚵,🚵🏻,🚵🏼,🚵🏽,🚵🏾,🚵🏿,🚵‍♀️,🚵🏻‍♀️,🚵🏼‍♀️,🚵🏽‍♀️,🚵🏾‍♀️,🚵🏿‍♀️,🚵‍♂️,🚵🏻‍♂️,🚵🏼‍♂️,🚵🏽‍♂️,🚵🏾‍♂️,🚵🏿‍♂️ +🧗,🧗,🧗🏻,🧗🏼,🧗🏽,🧗🏾,🧗🏿,🧗‍♀️,🧗🏻‍♀️,🧗🏼‍♀️,🧗🏽‍♀️,🧗🏾‍♀️,🧗🏿‍♀️,🧗‍♂️,🧗🏻‍♂️,🧗🏼‍♂️,🧗🏽‍♂️,🧗🏾‍♂️,🧗🏿‍♂️ +🏋️,🏋️,🏋🏻,🏋🏼,🏋🏽,🏋🏾,🏋🏿,🏋️‍♀️,🏋🏻‍♀️,🏋🏼‍♀️,🏋🏽‍♀️,🏋🏾‍♀️,🏋🏿‍♀️,🏋️‍♂️,🏋🏻‍♂️,🏋🏼‍♂️,🏋🏽‍♂️,🏋🏾‍♂️,🏋🏿‍♂️ +🤼,🤼,🤼‍♀️,🤼‍♂️ +🤹,🤹,🤹🏻,🤹🏼,🤹🏽,🤹🏾,🤹🏿,🤹‍♀️,🤹🏻‍♀️,🤹🏼‍♀️,🤹🏽‍♀️,🤹🏾‍♀️,🤹🏿‍♀️,🤹‍♂️,🤹🏻‍♂️,🤹🏼‍♂️,🤹🏽‍♂️,🤹🏾‍♂️,🤹🏿‍♂️ +🏌️,🏌️,🏌🏻,🏌🏼,🏌🏽,🏌🏾,🏌🏿,🏌️‍♀️,🏌🏻‍♀️,🏌🏼‍♀️,🏌🏽‍♀️,🏌🏾‍♀️,🏌🏿‍♀️,🏌️‍♂️,🏌🏻‍♂️,🏌🏼‍♂️,🏌🏽‍♂️,🏌🏾‍♂️,🏌🏿‍♂️ +🏇,🏇,🏇🏻,🏇🏼,🏇🏽,🏇🏾,🏇🏿 +🤺 +⛷️ +🏂,🏂,🏂🏻,🏂🏼,🏂🏽,🏂🏾,🏂🏿 +🪂 +🏄,🏄,🏄🏻,🏄🏼,🏄🏽,🏄🏾,🏄🏿,🏄‍♀️,🏄🏻‍♀️,🏄🏼‍♀️,🏄🏽‍♀️,🏄🏾‍♀️,🏄🏿‍♀️,🏄‍♂️,🏄🏻‍♂️,🏄🏼‍♂️,🏄🏽‍♂️,🏄🏾‍♂️,🏄🏿‍♂️ +🚣,🚣,🚣🏻,🚣🏼,🚣🏽,🚣🏾,🚣🏿,🚣‍♀️,🚣🏻‍♀️,🚣🏼‍♀️,🚣🏽‍♀️,🚣🏾‍♀️,🚣🏿‍♀️,🚣‍♂️,🚣🏻‍♂️,🚣🏼‍♂️,🚣🏽‍♂️,🚣🏾‍♂️,🚣🏿‍♂️ +🏊,🏊,🏊🏻,🏊🏼,🏊🏽,🏊🏾,🏊🏿,🏊‍♀️,🏊🏻‍♀️,🏊🏼‍♀️,🏊🏽‍♀️,🏊🏾‍♀️,🏊🏿‍♀️,🏊‍♂️,🏊🏻‍♂️,🏊🏼‍♂️,🏊🏽‍♂️,🏊🏾‍♂️,🏊🏿‍♂️ +🤽,🤽,🤽🏻,🤽🏼,🤽🏽,🤽🏾,🤽🏿,🤽‍♀️,🤽🏻‍♀️,🤽🏼‍♀️,🤽🏽‍♀️,🤽🏾‍♀️,🤽🏿‍♀️,🤽‍♂️,🤽🏻‍♂️,🤽🏼‍♂️,🤽🏽‍♂️,🤽🏾‍♂️,🤽🏿‍♂️ +🧜,🧜,🧜🏻,🧜🏼,🧜🏽,🧜🏾,🧜🏿,🧜‍♀️,🧜🏻‍♀️,🧜🏼‍♀️,🧜🏽‍♀️,🧜🏾‍♀️,🧜🏿‍♀️,🧜‍♂️,🧜🏻‍♂️,🧜🏼‍♂️,🧜🏽‍♂️,🧜🏾‍♂️,🧜🏿‍♂️ +🧚,🧚,🧚🏻,🧚🏼,🧚🏽,🧚🏾,🧚🏿,🧚‍♀️,🧚🏻‍♀️,🧚🏼‍♀️,🧚🏽‍♀️,🧚🏾‍♀️,🧚🏿‍♀️,🧚‍♂️,🧚🏻‍♂️,🧚🏼‍♂️,🧚🏽‍♂️,🧚🏾‍♂️,🧚🏿‍♂️ +🧞,🧞,🧞‍♀️,🧞‍♂️ +🧝,🧝,🧝🏻,🧝🏼,🧝🏽,🧝🏾,🧝🏿,🧝‍♀️,🧝🏻‍♀️,🧝🏼‍♀️,🧝🏽‍♀️,🧝🏾‍♀️,🧝🏿‍♀️,🧝‍♂️,🧝🏻‍♂️,🧝🏼‍♂️,🧝🏽‍♂️,🧝🏾‍♂️,🧝🏿‍♂️ +🧙,🧙,🧙🏻,🧙🏼,🧙🏽,🧙🏾,🧙🏿,🧙‍♀️,🧙🏻‍♀️,🧙🏼‍♀️,🧙🏽‍♀️,🧙🏾‍♀️,🧙🏿‍♀️,🧙‍♂️,🧙🏻‍♂️,🧙🏼‍♂️,🧙🏽‍♂️,🧙🏾‍♂️,🧙🏿‍♂️ +🧛,🧛,🧛🏻,🧛🏼,🧛🏽,🧛🏾,🧛🏿,🧛‍♀️,🧛🏻‍♀️,🧛🏼‍♀️,🧛🏽‍♀️,🧛🏾‍♀️,🧛🏿‍♀️,🧛‍♂️,🧛🏻‍♂️,🧛🏼‍♂️,🧛🏽‍♂️,🧛🏾‍♂️,🧛🏿‍♂️ +🧟,🧟,🧟‍♀️,🧟‍♂️ +🧌 +🦸,🦸,🦸🏻,🦸🏼,🦸🏽,🦸🏾,🦸🏿,🦸‍♀️,🦸🏻‍♀️,🦸🏼‍♀️,🦸🏽‍♀️,🦸🏾‍♀️,🦸🏿‍♀️,🦸‍♂️,🦸🏻‍♂️,🦸🏼‍♂️,🦸🏽‍♂️,🦸🏾‍♂️,🦸🏿‍♂️ +🦹,🦹,🦹🏻,🦹🏼,🦹🏽,🦹🏾,🦹🏿,🦹‍♀️,🦹🏻‍♀️,🦹🏼‍♀️,🦹🏽‍♀️,🦹🏾‍♀️,🦹🏿‍♀️,🦹‍♂️,🦹🏻‍♂️,🦹🏼‍♂️,🦹🏽‍♂️,🦹🏾‍♂️,🦹🏿‍♂️ +🥷,🥷,🥷🏻,🥷🏼,🥷🏽,🥷🏾,🥷🏿 +🧑‍🎄,🧑‍🎄,🧑🏻‍🎄,🧑🏼‍🎄,🧑🏽‍🎄,🧑🏾‍🎄,🧑🏿‍🎄,🤶,🤶🏻,🤶🏼,🤶🏽,🤶🏾,🤶🏿,🎅,🎅🏻,🎅🏼,🎅🏽,🎅🏾,🎅🏿 +👼,👼,👼🏻,👼🏼,👼🏽,👼🏾,👼🏿 +💂,💂,💂🏻,💂🏼,💂🏽,💂🏾,💂🏿,💂‍♀️,💂🏻‍♀️,💂🏼‍♀️,💂🏽‍♀️,💂🏾‍♀️,💂🏿‍♀️,💂‍♂️,💂🏻‍♂️,💂🏼‍♂️,💂🏽‍♂️,💂🏾‍♂️,💂🏿‍♂️ +🫅,🫅,🫅🏻,🫅🏼,🫅🏽,🫅🏾,🫅🏿,👸,👸🏻,👸🏼,👸🏽,👸🏾,👸🏿,🤴,🤴🏻,🤴🏼,🤴🏽,🤴🏾,🤴🏿 +🤵,🤵,🤵🏻,🤵🏼,🤵🏽,🤵🏾,🤵🏿,🤵‍♀️,🤵🏻‍♀️,🤵🏼‍♀️,🤵🏽‍♀️,🤵🏾‍♀️,🤵🏿‍♀️,🤵‍♂️,🤵🏻‍♂️,🤵🏼‍♂️,🤵🏽‍♂️,🤵🏾‍♂️,🤵🏿‍♂️ +👰,👰,👰🏻,👰🏼,👰🏽,👰🏾,👰🏿,👰‍♀️,👰🏻‍♀️,👰🏼‍♀️,👰🏽‍♀️,👰🏾‍♀️,👰🏿‍♀️,👰‍♂️,👰🏻‍♂️,👰🏼‍♂️,👰🏽‍♂️,👰🏾‍♂️,👰🏿‍♂️ +🧑‍🚀,🧑‍🚀,🧑🏻‍🚀,🧑🏼‍🚀,🧑🏽‍🚀,🧑🏾‍🚀,🧑🏿‍🚀,👩‍🚀,👩🏻‍🚀,👩🏼‍🚀,👩🏽‍🚀,👩🏾‍🚀,👩🏿‍🚀,👨‍🚀,👨🏻‍🚀,👨🏼‍🚀,👨🏽‍🚀,👨🏾‍🚀,👨🏿‍🚀 +👷,👷,👷🏻,👷🏼,👷🏽,👷🏾,👷🏿,👷‍♀️,👷🏻‍♀️,👷🏼‍♀️,👷🏽‍♀️,👷🏾‍♀️,👷🏿‍♀️,👷‍♂️,👷🏻‍♂️,👷🏼‍♂️,👷🏽‍♂️,👷🏾‍♂️,👷🏿‍♂️ +👮,👮,👮🏻,👮🏼,👮🏽,👮🏾,👮🏿,👮‍♀️,👮🏻‍♀️,👮🏼‍♀️,👮🏽‍♀️,👮🏾‍♀️,👮🏿‍♀️,👮‍♂️,👮🏻‍♂️,👮🏼‍♂️,👮🏽‍♂️,👮🏾‍♂️,👮🏿‍♂️ +🕵️,🕵️,🕵🏻,🕵🏼,🕵🏽,🕵🏾,🕵🏿,🕵️‍♀️,🕵🏻‍♀️,🕵🏼‍♀️,🕵🏽‍♀️,🕵🏾‍♀️,🕵🏿‍♀️,🕵️‍♂️,🕵🏻‍♂️,🕵🏼‍♂️,🕵🏽‍♂️,🕵🏾‍♂️,🕵🏿‍♂️ +🧑‍✈️,🧑‍✈️,🧑🏻‍✈️,🧑🏼‍✈️,🧑🏽‍✈️,🧑🏾‍✈️,🧑🏿‍✈️,👩‍✈️,👩🏻‍✈️,👩🏼‍✈️,👩🏽‍✈️,👩🏾‍✈️,👩🏿‍✈️,👨‍✈️,👨🏻‍✈️,👨🏼‍✈️,👨🏽‍✈️,👨🏾‍✈️,👨🏿‍✈️ +🧑‍🔬,🧑‍🔬,🧑🏻‍🔬,🧑🏼‍🔬,🧑🏽‍🔬,🧑🏾‍🔬,🧑🏿‍🔬,👩‍🔬,👩🏻‍🔬,👩🏼‍🔬,👩🏽‍🔬,👩🏾‍🔬,👩🏿‍🔬,👨‍🔬,👨🏻‍🔬,👨🏼‍🔬,👨🏽‍🔬,👨🏾‍🔬,👨🏿‍🔬 +🧑‍⚕️,🧑‍⚕️,🧑🏻‍⚕️,🧑🏼‍⚕️,🧑🏽‍⚕️,🧑🏾‍⚕️,🧑🏿‍⚕️,👩‍⚕️,👩🏻‍⚕️,👩🏼‍⚕️,👩🏽‍⚕️,👩🏾‍⚕️,👩🏿‍⚕️,👨‍⚕️,👨🏻‍⚕️,👨🏼‍⚕️,👨🏽‍⚕️,👨🏾‍⚕️,👨🏿‍⚕️ +🧑‍🔧,🧑‍🔧,🧑🏻‍🔧,🧑🏼‍🔧,🧑🏽‍🔧,🧑🏾‍🔧,🧑🏿‍🔧,👩‍🔧,👩🏻‍🔧,👩🏼‍🔧,👩🏽‍🔧,👩🏾‍🔧,👩🏿‍🔧,👨‍🔧,👨🏻‍🔧,👨🏼‍🔧,👨🏽‍🔧,👨🏾‍🔧,👨🏿‍🔧 +🧑‍🏭,🧑‍🏭,🧑🏻‍🏭,🧑🏼‍🏭,🧑🏽‍🏭,🧑🏾‍🏭,🧑🏿‍🏭,👩‍🏭,👩🏻‍🏭,👩🏼‍🏭,👩🏽‍🏭,👩🏾‍🏭,👩🏿‍🏭,👨‍🏭,👨🏻‍🏭,👨🏼‍🏭,👨🏽‍🏭,👨🏾‍🏭,👨🏿‍🏭 +🧑‍🚒,🧑‍🚒,🧑🏻‍🚒,🧑🏼‍🚒,🧑🏽‍🚒,🧑🏾‍🚒,🧑🏿‍🚒,👩‍🚒,👩🏻‍🚒,👩🏼‍🚒,👩🏽‍🚒,👩🏾‍🚒,👩🏿‍🚒,👨‍🚒,👨🏻‍🚒,👨🏼‍🚒,👨🏽‍🚒,👨🏾‍🚒,👨🏿‍🚒 +🧑‍🌾,🧑‍🌾,🧑🏻‍🌾,🧑🏼‍🌾,🧑🏽‍🌾,🧑🏾‍🌾,🧑🏿‍🌾,👩‍🌾,👩🏻‍🌾,👩🏼‍🌾,👩🏽‍🌾,👩🏾‍🌾,👩🏿‍🌾,👨‍🌾,👨🏻‍🌾,👨🏼‍🌾,👨🏽‍🌾,👨🏾‍🌾,👨🏿‍🌾 +🧑‍🏫,🧑‍🏫,🧑🏻‍🏫,🧑🏼‍🏫,🧑🏽‍🏫,🧑🏾‍🏫,🧑🏿‍🏫,👩‍🏫,👩🏻‍🏫,👩🏼‍🏫,👩🏽‍🏫,👩🏾‍🏫,👩🏿‍🏫,👨‍🏫,👨🏻‍🏫,👨🏼‍🏫,👨🏽‍🏫,👨🏾‍🏫,👨🏿‍🏫 +🧑‍🎓,🧑‍🎓,🧑🏻‍🎓,🧑🏼‍🎓,🧑🏽‍🎓,🧑🏾‍🎓,🧑🏿‍🎓,👩‍🎓,👩🏻‍🎓,👩🏼‍🎓,👩🏽‍🎓,👩🏾‍🎓,👩🏿‍🎓,👨‍🎓,👨🏻‍🎓,👨🏼‍🎓,👨🏽‍🎓,👨🏾‍🎓,👨🏿‍🎓 +🧑‍💼,🧑‍💼,🧑🏻‍💼,🧑🏼‍💼,🧑🏽‍💼,🧑🏾‍💼,🧑🏿‍💼,👩‍💼,👩🏻‍💼,👩🏼‍💼,👩🏽‍💼,👩🏾‍💼,👩🏿‍💼,👨‍💼,👨🏻‍💼,👨🏼‍💼,👨🏽‍💼,👨🏾‍💼,👨🏿‍💼 +🧑‍⚖️,🧑‍⚖️,🧑🏻‍⚖️,🧑🏼‍⚖️,🧑🏽‍⚖️,🧑🏾‍⚖️,🧑🏿‍⚖️,👩‍⚖️,👩🏻‍⚖️,👩🏼‍⚖️,👩🏽‍⚖️,👩🏾‍⚖️,👩🏿‍⚖️,👨‍⚖️,👨🏻‍⚖️,👨🏼‍⚖️,👨🏽‍⚖️,👨🏾‍⚖️,👨🏿‍⚖️ +🧑‍💻,🧑‍💻,🧑🏻‍💻,🧑🏼‍💻,🧑🏽‍💻,🧑🏾‍💻,🧑🏿‍💻,👩‍💻,👩🏻‍💻,👩🏼‍💻,👩🏽‍💻,👩🏾‍💻,👩🏿‍💻,👨‍💻,👨🏻‍💻,👨🏼‍💻,👨🏽‍💻,👨🏾‍💻,👨🏿‍💻 +🧑‍🎤,🧑‍🎤,🧑🏻‍🎤,🧑🏼‍🎤,🧑🏽‍🎤,🧑🏾‍🎤,🧑🏿‍🎤,👩‍🎤,👩🏻‍🎤,👩🏼‍🎤,👩🏽‍🎤,👩🏾‍🎤,👩🏿‍🎤,👨‍🎤,👨🏻‍🎤,👨🏼‍🎤,👨🏽‍🎤,👨🏾‍🎤,👨🏿‍🎤 +🧑‍🎨,🧑‍🎨,🧑🏻‍🎨,🧑🏼‍🎨,🧑🏽‍🎨,🧑🏾‍🎨,🧑🏿‍🎨,👩‍🎨,👩🏻‍🎨,👩🏼‍🎨,👩🏽‍🎨,👩🏾‍🎨,👩🏿‍🎨,👨‍🎨,👨🏻‍🎨,👨🏼‍🎨,👨🏽‍🎨,👨🏾‍🎨,👨🏿‍🎨 +🧑‍🍳,🧑‍🍳,🧑🏻‍🍳,🧑🏼‍🍳,🧑🏽‍🍳,🧑🏾‍🍳,🧑🏿‍🍳,👩‍🍳,👩🏻‍🍳,👩🏼‍🍳,👩🏽‍🍳,👩🏾‍🍳,👩🏿‍🍳,👨‍🍳,👨🏻‍🍳,👨🏼‍🍳,👨🏽‍🍳,👨🏾‍🍳,👨🏿‍🍳 +👳,👳,👳🏻,👳🏼,👳🏽,👳🏾,👳🏿,👳‍♀️,👳🏻‍♀️,👳🏼‍♀️,👳🏽‍♀️,👳🏾‍♀️,👳🏿‍♀️,👳‍♂️,👳🏻‍♂️,👳🏼‍♂️,👳🏽‍♂️,👳🏾‍♂️,👳🏿‍♂️ +🧕,🧕,🧕🏻,🧕🏼,🧕🏽,🧕🏾,🧕🏿 +👲,👲,👲🏻,👲🏼,👲🏽,👲🏾,👲🏿 +👶,👶,👶🏻,👶🏼,👶🏽,👶🏾,👶🏿 +🧒,🧒,🧒🏻,🧒🏼,🧒🏽,🧒🏾,🧒🏿,👧,👧🏻,👧🏼,👧🏽,👧🏾,👧🏿,👦,👦🏻,👦🏼,👦🏽,👦🏾,👦🏿 +🧑,🧑,🧑🏻,🧑🏼,🧑🏽,🧑🏾,🧑🏿,👩,👩🏻,👩🏼,👩🏽,👩🏾,👩🏿,👨,👨🏻,👨🏼,👨🏽,👨🏾,👨🏿 +🧓,🧓,🧓🏻,🧓🏼,🧓🏽,🧓🏾,🧓🏿,👵,👵🏻,👵🏼,👵🏽,👵🏾,👵🏿,👴,👴🏻,👴🏼,👴🏽,👴🏾,👴🏿 +🧑‍🦳,🧑‍🦳,🧑🏻‍🦳,🧑🏼‍🦳,🧑🏽‍🦳,🧑🏾‍🦳,🧑🏿‍🦳,👩‍🦳,👩🏻‍🦳,👩🏼‍🦳,👩🏽‍🦳,👩🏾‍🦳,👩🏿‍🦳,👨‍🦳,👨🏻‍🦳,👨🏼‍🦳,👨🏽‍🦳,👨🏾‍🦳,👨🏿‍🦳 +🧑‍🦰,🧑‍🦰,🧑🏻‍🦰,🧑🏼‍🦰,🧑🏽‍🦰,🧑🏾‍🦰,🧑🏿‍🦰,👩‍🦰,👩🏻‍🦰,👩🏼‍🦰,👩🏽‍🦰,👩🏾‍🦰,👩🏿‍🦰,👨‍🦰,👨🏻‍🦰,👨🏼‍🦰,👨🏽‍🦰,👨🏾‍🦰,👨🏿‍🦰 +👱,👱,👱🏻,👱🏼,👱🏽,👱🏾,👱🏿,👱‍♀️,👱🏻‍♀️,👱🏼‍♀️,👱🏽‍♀️,👱🏾‍♀️,👱🏿‍♀️,👱‍♂️,👱🏻‍♂️,👱🏼‍♂️,👱🏽‍♂️,👱🏾‍♂️,👱🏿‍♂️ +🧑‍🦱,🧑‍🦱,🧑🏻‍🦱,🧑🏼‍🦱,🧑🏽‍🦱,🧑🏾‍🦱,🧑🏿‍🦱,👩‍🦱,👩🏻‍🦱,👩🏼‍🦱,👩🏽‍🦱,👩🏾‍🦱,👩🏿‍🦱,👨‍🦱,👨🏻‍🦱,👨🏼‍🦱,👨🏽‍🦱,👨🏾‍🦱,👨🏿‍🦱 +🧑‍🦲,🧑‍🦲,🧑🏻‍🦲,🧑🏼‍🦲,🧑🏽‍🦲,🧑🏾‍🦲,🧑🏿‍🦲,👩‍🦲,👩🏻‍🦲,👩🏼‍🦲,👩🏽‍🦲,👩🏾‍🦲,👩🏿‍🦲,👨‍🦲,👨🏻‍🦲,👨🏼‍🦲,👨🏽‍🦲,👨🏾‍🦲,👨🏿‍🦲 +🧔,🧔,🧔🏻,🧔🏼,🧔🏽,🧔🏾,🧔🏿,🧔‍♀️,🧔🏻‍♀️,🧔🏼‍♀️,🧔🏽‍♀️,🧔🏾‍♀️,🧔🏿‍♀️,🧔‍♂️,🧔🏻‍♂️,🧔🏼‍♂️,🧔🏽‍♂️,🧔🏾‍♂️,🧔🏿‍♂️ +🕴️,🕴️,🕴🏻,🕴🏼,🕴🏽,🕴🏾,🕴🏿 +💃,💃,💃🏻,💃🏼,💃🏽,💃🏾,💃🏿 +🕺,🕺,🕺🏻,🕺🏼,🕺🏽,🕺🏾,🕺🏿 +👯,👯,👯‍♂️,👯‍♀️ +🧑‍🤝‍🧑,🧑‍🤝‍🧑,🧑🏻‍🤝‍🧑🏻,🧑🏻‍🤝‍🧑🏼,🧑🏻‍🤝‍🧑🏽,🧑🏻‍🤝‍🧑🏾,🧑🏻‍🤝‍🧑🏿,🧑🏼‍🤝‍🧑🏻,🧑🏼‍🤝‍🧑🏼,🧑🏼‍🤝‍🧑🏽,🧑🏼‍🤝‍🧑🏾,🧑🏼‍🤝‍🧑🏿,🧑🏽‍🤝‍🧑🏻,🧑🏽‍🤝‍🧑🏼,🧑🏽‍🤝‍🧑🏽,🧑🏽‍🤝‍🧑🏾,🧑🏽‍🤝‍🧑🏿,🧑🏾‍🤝‍🧑🏻,🧑🏾‍🤝‍🧑🏼,🧑🏾‍🤝‍🧑🏽,🧑🏾‍🤝‍🧑🏾,🧑🏾‍🤝‍🧑🏿,🧑🏿‍🤝‍🧑🏻,🧑🏿‍🤝‍🧑🏼,🧑🏿‍🤝‍🧑🏽,🧑🏿‍🤝‍🧑🏾,🧑🏿‍🤝‍🧑🏿 +👭,👭,👭🏻,👩🏻‍🤝‍👩🏼,👩🏻‍🤝‍👩🏽,👩🏻‍🤝‍👩🏾,👩🏻‍🤝‍👩🏿,👩🏼‍🤝‍👩🏻,👭🏼,👩🏼‍🤝‍👩🏽,👩🏼‍🤝‍👩🏾,👩🏼‍🤝‍👩🏿,👩🏽‍🤝‍👩🏻,👩🏽‍🤝‍👩🏼,👭🏽,👩🏽‍🤝‍👩🏾,👩🏽‍🤝‍👩🏿,👩🏾‍🤝‍👩🏻,👩🏾‍🤝‍👩🏼,👩🏾‍🤝‍👩🏽,👭🏾,👩🏾‍🤝‍👩🏿,👩🏿‍🤝‍👩🏻,👩🏿‍🤝‍👩🏼,👩🏿‍🤝‍👩🏽,👩🏿‍🤝‍👩🏾,👭🏿 +👬,👬,👬🏻,👨🏻‍🤝‍👨🏼,👨🏻‍🤝‍👨🏽,👨🏻‍🤝‍👨🏾,👨🏻‍🤝‍👨🏿,👨🏼‍🤝‍👨🏻,👬🏼,👨🏼‍🤝‍👨🏽,👨🏼‍🤝‍👨🏾,👨🏼‍🤝‍👨🏿,👨🏽‍🤝‍👨🏻,👨🏽‍🤝‍👨🏼,👬🏽,👨🏽‍🤝‍👨🏾,👨🏽‍🤝‍👨🏿,👨🏾‍🤝‍👨🏻,👨🏾‍🤝‍👨🏼,👨🏾‍🤝‍👨🏽,👬🏾,👨🏾‍🤝‍👨🏿,👨🏿‍🤝‍👨🏻,👨🏿‍🤝‍👨🏼,👨🏿‍🤝‍👨🏽,👨🏿‍🤝‍👨🏾,👬🏿 +👫,👫,👫🏻,👩🏻‍🤝‍👨🏼,👩🏻‍🤝‍👨🏽,👩🏻‍🤝‍👨🏾,👩🏻‍🤝‍👨🏿,👩🏼‍🤝‍👨🏻,👫🏼,👩🏼‍🤝‍👨🏽,👩🏼‍🤝‍👨🏾,👩🏼‍🤝‍👨🏿,👩🏽‍🤝‍👨🏻,👩🏽‍🤝‍👨🏼,👫🏽,👩🏽‍🤝‍👨🏾,👩🏽‍🤝‍👨🏿,👩🏾‍🤝‍👨🏻,👩🏾‍🤝‍👨🏼,👩🏾‍🤝‍👨🏽,👫🏾,👩🏾‍🤝‍👨🏿,👩🏿‍🤝‍👨🏻,👩🏿‍🤝‍👨🏼,👩🏿‍🤝‍👨🏽,👩🏿‍🤝‍👨🏾,👫🏿 +💏,💏,💏🏻,🧑🏻‍❤️‍💋‍🧑🏼,🧑🏻‍❤️‍💋‍🧑🏽,🧑🏻‍❤️‍💋‍🧑🏾,🧑🏻‍❤️‍💋‍🧑🏿,🧑🏼‍❤️‍💋‍🧑🏻,💏🏼,🧑🏼‍❤️‍💋‍🧑🏽,🧑🏼‍❤️‍💋‍🧑🏾,🧑🏼‍❤️‍💋‍🧑🏿,🧑🏽‍❤️‍💋‍🧑🏻,🧑🏽‍❤️‍💋‍🧑🏼,💏🏽,🧑🏽‍❤️‍💋‍🧑🏾,🧑🏽‍❤️‍💋‍🧑🏿,🧑🏾‍❤️‍💋‍🧑🏻,🧑🏾‍❤️‍💋‍🧑🏼,🧑🏾‍❤️‍💋‍🧑🏽,💏🏾,🧑🏾‍❤️‍💋‍🧑🏿,🧑🏿‍❤️‍💋‍🧑🏻,🧑🏿‍❤️‍💋‍🧑🏼,🧑🏿‍❤️‍💋‍🧑🏽,🧑🏿‍❤️‍💋‍🧑🏾,💏🏿 +👩‍❤️‍💋‍👨,👩‍❤️‍💋‍👨,👩🏻‍❤️‍💋‍👨🏻,👩🏻‍❤️‍💋‍👨🏼,👩🏻‍❤️‍💋‍👨🏽,👩🏻‍❤️‍💋‍👨🏾,👩🏻‍❤️‍💋‍👨🏿,👩🏼‍❤️‍💋‍👨🏻,👩🏼‍❤️‍💋‍👨🏼,👩🏼‍❤️‍💋‍👨🏽,👩🏼‍❤️‍💋‍👨🏾,👩🏼‍❤️‍💋‍👨🏿,👩🏽‍❤️‍💋‍👨🏻,👩🏽‍❤️‍💋‍👨🏼,👩🏽‍❤️‍💋‍👨🏽,👩🏽‍❤️‍💋‍👨🏾,👩🏽‍❤️‍💋‍👨🏿,👩🏾‍❤️‍💋‍👨🏻,👩🏾‍❤️‍💋‍👨🏼,👩🏾‍❤️‍💋‍👨🏽,👩🏾‍❤️‍💋‍👨🏾,👩🏾‍❤️‍💋‍👨🏿,👩🏿‍❤️‍💋‍👨🏻,👩🏿‍❤️‍💋‍👨🏼,👩🏿‍❤️‍💋‍👨🏽,👩🏿‍❤️‍💋‍👨🏾,👩🏿‍❤️‍💋‍👨🏿 +👨‍❤️‍💋‍👨,👨‍❤️‍💋‍👨,👨🏻‍❤️‍💋‍👨🏻,👨🏻‍❤️‍💋‍👨🏼,👨🏻‍❤️‍💋‍👨🏽,👨🏻‍❤️‍💋‍👨🏾,👨🏻‍❤️‍💋‍👨🏿,👨🏼‍❤️‍💋‍👨🏻,👨🏼‍❤️‍💋‍👨🏼,👨🏼‍❤️‍💋‍👨🏽,👨🏼‍❤️‍💋‍👨🏾,👨🏼‍❤️‍💋‍👨🏿,👨🏽‍❤️‍💋‍👨🏻,👨🏽‍❤️‍💋‍👨🏼,👨🏽‍❤️‍💋‍👨🏽,👨🏽‍❤️‍💋‍👨🏾,👨🏽‍❤️‍💋‍👨🏿,👨🏾‍❤️‍💋‍👨🏻,👨🏾‍❤️‍💋‍👨🏼,👨🏾‍❤️‍💋‍👨🏽,👨🏾‍❤️‍💋‍👨🏾,👨🏾‍❤️‍💋‍👨🏿,👨🏿‍❤️‍💋‍👨🏻,👨🏿‍❤️‍💋‍👨🏼,👨🏿‍❤️‍💋‍👨🏽,👨🏿‍❤️‍💋‍👨🏾,👨🏿‍❤️‍💋‍👨🏿 +👩‍❤️‍💋‍👩,👩‍❤️‍💋‍👩,👩🏻‍❤️‍💋‍👩🏻,👩🏻‍❤️‍💋‍👩🏼,👩🏻‍❤️‍💋‍👩🏽,👩🏻‍❤️‍💋‍👩🏾,👩🏻‍❤️‍💋‍👩🏿,👩🏼‍❤️‍💋‍👩🏻,👩🏼‍❤️‍💋‍👩🏼,👩🏼‍❤️‍💋‍👩🏽,👩🏼‍❤️‍💋‍👩🏾,👩🏼‍❤️‍💋‍👩🏿,👩🏽‍❤️‍💋‍👩🏻,👩🏽‍❤️‍💋‍👩🏼,👩🏽‍❤️‍💋‍👩🏽,👩🏽‍❤️‍💋‍👩🏾,👩🏽‍❤️‍💋‍👩🏿,👩🏾‍❤️‍💋‍👩🏻,👩🏾‍❤️‍💋‍👩🏼,👩🏾‍❤️‍💋‍👩🏽,👩🏾‍❤️‍💋‍👩🏾,👩🏾‍❤️‍💋‍👩🏿,👩🏿‍❤️‍💋‍👩🏻,👩🏿‍❤️‍💋‍👩🏼,👩🏿‍❤️‍💋‍👩🏽,👩🏿‍❤️‍💋‍👩🏾,👩🏿‍❤️‍💋‍👩🏿 +💑,💑,💑🏻,🧑🏻‍❤️‍🧑🏼,🧑🏻‍❤️‍🧑🏽,🧑🏻‍❤️‍🧑🏾,🧑🏻‍❤️‍🧑🏿,🧑🏼‍❤️‍🧑🏻,💑🏼,🧑🏼‍❤️‍🧑🏽,🧑🏼‍❤️‍🧑🏾,🧑🏼‍❤️‍🧑🏿,🧑🏽‍❤️‍🧑🏻,🧑🏽‍❤️‍🧑🏼,💑🏽,🧑🏽‍❤️‍🧑🏾,🧑🏽‍❤️‍🧑🏿,🧑🏾‍❤️‍🧑🏻,🧑🏾‍❤️‍🧑🏼,🧑🏾‍❤️‍🧑🏽,💑🏾,🧑🏾‍❤️‍🧑🏿,🧑🏿‍❤️‍🧑🏻,🧑🏿‍❤️‍🧑🏼,🧑🏿‍❤️‍🧑🏽,🧑🏿‍❤️‍🧑🏾,💑🏿 +👩‍❤️‍👨,👩‍❤️‍👨,👩🏻‍❤️‍👨🏻,👩🏻‍❤️‍👨🏼,👩🏻‍❤️‍👨🏽,👩🏻‍❤️‍👨🏾,👩🏻‍❤️‍👨🏿,👩🏼‍❤️‍👨🏻,👩🏼‍❤️‍👨🏼,👩🏼‍❤️‍👨🏽,👩🏼‍❤️‍👨🏾,👩🏼‍❤️‍👨🏿,👩🏽‍❤️‍👨🏻,👩🏽‍❤️‍👨🏼,👩🏽‍❤️‍👨🏽,👩🏽‍❤️‍👨🏾,👩🏽‍❤️‍👨🏿,👩🏾‍❤️‍👨🏻,👩🏾‍❤️‍👨🏼,👩🏾‍❤️‍👨🏽,👩🏾‍❤️‍👨🏾,👩🏾‍❤️‍👨🏿,👩🏿‍❤️‍👨🏻,👩🏿‍❤️‍👨🏼,👩🏿‍❤️‍👨🏽,👩🏿‍❤️‍👨🏾,👩🏿‍❤️‍👨🏿 +👨‍❤️‍👨,👨‍❤️‍👨,👨🏻‍❤️‍👨🏻,👨🏻‍❤️‍👨🏼,👨🏻‍❤️‍👨🏽,👨🏻‍❤️‍👨🏾,👨🏻‍❤️‍👨🏿,👨🏼‍❤️‍👨🏻,👨🏼‍❤️‍👨🏼,👨🏼‍❤️‍👨🏽,👨🏼‍❤️‍👨🏾,👨🏼‍❤️‍👨🏿,👨🏽‍❤️‍👨🏻,👨🏽‍❤️‍👨🏼,👨🏽‍❤️‍👨🏽,👨🏽‍❤️‍👨🏾,👨🏽‍❤️‍👨🏿,👨🏾‍❤️‍👨🏻,👨🏾‍❤️‍👨🏼,👨🏾‍❤️‍👨🏽,👨🏾‍❤️‍👨🏾,👨🏾‍❤️‍👨🏿,👨🏿‍❤️‍👨🏻,👨🏿‍❤️‍👨🏼,👨🏿‍❤️‍👨🏽,👨🏿‍❤️‍👨🏾,👨🏿‍❤️‍👨🏿 +👩‍❤️‍👩,👩‍❤️‍👩,👩🏻‍❤️‍👩🏻,👩🏻‍❤️‍👩🏼,👩🏻‍❤️‍👩🏽,👩🏻‍❤️‍👩🏾,👩🏻‍❤️‍👩🏿,👩🏼‍❤️‍👩🏻,👩🏼‍❤️‍👩🏼,👩🏼‍❤️‍👩🏽,👩🏼‍❤️‍👩🏾,👩🏼‍❤️‍👩🏿,👩🏽‍❤️‍👩🏻,👩🏽‍❤️‍👩🏼,👩🏽‍❤️‍👩🏽,👩🏽‍❤️‍👩🏾,👩🏽‍❤️‍👩🏿,👩🏾‍❤️‍👩🏻,👩🏾‍❤️‍👩🏼,👩🏾‍❤️‍👩🏽,👩🏾‍❤️‍👩🏾,👩🏾‍❤️‍👩🏿,👩🏿‍❤️‍👩🏻,👩🏿‍❤️‍👩🏼,👩🏿‍❤️‍👩🏽,👩🏿‍❤️‍👩🏾,👩🏿‍❤️‍👩🏿 +🫄,🫄,🫄🏻,🫄🏼,🫄🏽,🫄🏾,🫄🏿,🤰,🤰🏻,🤰🏼,🤰🏽,🤰🏾,🤰🏿,🫃,🫃🏻,🫃🏼,🫃🏽,🫃🏾,🫃🏿 +🤱,🤱,🤱🏻,🤱🏼,🤱🏽,🤱🏾,🤱🏿 +🧑‍🍼,🧑‍🍼,🧑🏻‍🍼,🧑🏼‍🍼,🧑🏽‍🍼,🧑🏾‍🍼,🧑🏿‍🍼,👩‍🍼,👩🏻‍🍼,👩🏼‍🍼,👩🏽‍🍼,👩🏾‍🍼,👩🏿‍🍼,👨‍🍼,👨🏻‍🍼,👨🏼‍🍼,👨🏽‍🍼,👨🏾‍🍼,👨🏿‍🍼 diff --git a/emojipicker/app/src/main/androidx/res/raw/emoji_category_symbols.csv b/emojipicker/app/src/main/androidx/res/raw/emoji_category_symbols.csv new file mode 100644 index 000000000..d917e2747 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/raw/emoji_category_symbols.csv @@ -0,0 +1,261 @@ +🔴 +🟠 +🟡 +🟢 +🔵 +🟣 +🟤 +⚫ +⚪ +🟥 +🟧 +🟨 +🟩 +🟦 +🟪 +🟫 +⬛ +⬜ +❤️ +🧡 +💛 +💚 +💙 +💜 +🤎 +🖤 +🤍 +🩷 +🩵 +🩶 +♥️ +♦️ +♣️ +♠️ +♈ +♉ +♊ +♋ +♌ +♍ +♎ +♏ +♐ +♑ +♒ +♓ +⛎ +♀️ +♂️ +⚧️ +💭 +🗯️ +💬 +🗨️ +❕ +❔ +❗ +❓ +⁉️ +‼️ +⭕ +❌ +🚫 +🚳 +🚭 +🚯 +🚱 +🚷 +📵 +🔞 +🔕 +🔇 +🅰️ +🆎 +🅱️ +🅾️ +🆑 +🆘 +🛑 +⛔ +📛 +♨️ +💢 +🔻 +🔺 +🉐 +㊙️ +㊗️ +🈴 +🈵 +🈹 +🈲 +🉑 +🈶 +🈚 +🈸 +🈺 +🈷️ +✴️ +🔶 +🔸 +🔆 +🔅 +🆚 +🎦 +📶 +🔁 +🔂 +🔀 +▶️ +⏩ +⏭️ +⏯️ +◀️ +⏪ +⏮️ +🔼 +⏫ +🔽 +⏬ +⏸️ +⏹️ +⏺️ +⏏️ +📴 +🛜 +📳 +📲 +☢️ +☣️ +⚠️ +🚸 +⚜️ +🔱 +〽️ +🔰 +✳️ +❇️ +♻️ +💱 +💲 +💹 +🈯 +❎ +✅ +✔️ +☑️ +⬆️ +↗️ +➡️ +↘️ +⬇️ +↙️ +⬅️ +↖️ +↕️ +↔️ +↩️ +↪️ +⤴️ +⤵️ +🔃 +🔄 +🔙 +🔛 +🔝 +🔚 +🔜 +🆕 +🆓 +🆙 +🆗 +🆒 +🆖 +ℹ️ +🅿️ +🈁 +🈂️ +🈳 +🔣 +🔤 +🔠 +🔡 +🔢 +#️⃣ +*️⃣ +0️⃣ +1️⃣ +2️⃣ +3️⃣ +4️⃣ +5️⃣ +6️⃣ +7️⃣ +8️⃣ +9️⃣ +🔟 +🌐 +💠 +🔷 +🔹 +🏧 +Ⓜ️ +🚾 +🚻 +🚹 +🚺 +♿ +🚼 +🛗 +🚮 +🚰 +🛂 +🛃 +🛄 +🛅 +💟 +⚛️ +🛐 +🕉️ +☸️ +☮️ +☯️ +☪️ +🪯 +✝️ +☦️ +✡️ +🔯 +🕎 +♾️ +🆔 +🧑‍🧑‍🧒 +🧑‍🧑‍🧒‍🧒 +🧑‍🧒 +🧑‍🧒‍🧒 +⚕️ +🎼 +🎵 +🎶 +✖️ +➕ +➖ +➗ +🟰 +➰ +➿ +〰️ +©️ +®️ +™️ +🔘 +🔳 +◼️ +◾ +▪️ +🔲 +◻️ +◽ +▫️ +👁️‍🗨️ diff --git a/emojipicker/app/src/main/androidx/res/raw/emoji_category_travel_places.csv b/emojipicker/app/src/main/androidx/res/raw/emoji_category_travel_places.csv new file mode 100644 index 000000000..8704e9563 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/raw/emoji_category_travel_places.csv @@ -0,0 +1,122 @@ +🛑 +🚧 +🚨 +⛽ +🛢️ +🧭 +🛞 +🛟 +⚓ +🚏 +🚇 +🚥 +🚦 +🛴 +🦽 +🦼 +🩼 +🚲 +🛵 +🏍️ +🚙 +🚗 +🛻 +🚐 +🚚 +🚛 +🚜 +🏎️ +🚒 +🚑 +🚓 +🚕 +🛺 +🚌 +🚈 +🚝 +🚅 +🚄 +🚂 +🚃 +🚋 +🚎 +🚞 +🚊 +🚉 +🚍 +🚔 +🚘 +🚖 +🚆 +🚢 +🛳️ +🛥️ +🚤 +⛴️ +⛵ +🛶 +🚟 +🚠 +🚡 +🚁 +🛸 +🚀 +✈️ +🛫 +🛬 +🛩️ +🛝 +🎢 +🎡 +🎠 +🎪 +🗼 +🗽 +🗿 +🗻 +🏛️ +💈 +⛲ +⛩️ +🕍 +🕌 +🕋 +🛕 +⛪ +💒 +🏩 +🏯 +🏰 +🏗️ +🏢 +🏭 +🏬 +🏪 +🏟️ +🏦 +🏫 +🏨 +🏣 +🏤 +🏥 +🏚️ +🏠 +🏡 +🏘️ +🛖 +⛺ +🏕️ +⛱️ +🏙️ +🌆 +🌇 +🌃 +🌉 +🌁 +🛤️ +🛣️ +🗾 +🗺️ +🌐 +💺 +🧳 diff --git a/emojipicker/app/src/main/androidx/res/values-af/strings.xml b/emojipicker/app/src/main/androidx/res/values-af/strings.xml new file mode 100644 index 000000000..ef7bb7c44 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-af/strings.xml @@ -0,0 +1,42 @@ + + + + + "ONLANGS GEBRUIK" + "EMOSIEKONE EN EMOSIES" + "MENSE" + "DIERE EN NATUUR" + "KOS EN DRINKGOED" + "REIS EN PLEKKE" + "AKTIWITEITE EN GELEENTHEDE" + "VOORWERPE" + "SIMBOLE" + "VLAE" + "Geen emosiekone beskikbaar nie" + "Jy het nog geen emosiekone gebruik nie" + "emosiekoon-tweerigtingoorskakelaar" + "rigting waarin emosiekoon wys is gewissel" + "emosiekoonvariantkieser" + "%1$s en %2$s" + "skadu" + "ligte velkleur" + "mediumligte velkleur" + "medium velkleur" + "mediumdonker velkleur" + "donker velkleur" + diff --git a/emojipicker/app/src/main/androidx/res/values-am/strings.xml b/emojipicker/app/src/main/androidx/res/values-am/strings.xml new file mode 100644 index 000000000..5be491cca --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-am/strings.xml @@ -0,0 +1,42 @@ + + + + + "በቅርብ ጊዜ ጥቅም ላይ የዋለ" + "ሳቂታዎች እና ስሜቶች" + "ሰዎች" + "እንስሳት እና ተፈጥሮ" + "ምግብ እና መጠጥ" + "ጉዞ እና ቦታዎች" + "እንቅስቃሴዎች እና ክስተቶች" + "ነገሮች" + "ምልክቶች" + "ባንዲራዎች" + "ምንም ስሜት ገላጭ ምስሎች አይገኙም" + "ምንም ስሜት ገላጭ ምስሎችን እስካሁን አልተጠቀሙም" + "የስሜት ገላጭ ምስል ባለሁለት አቅጣጫ መቀያየሪያ" + "የስሜት ገላጭ ምስል አቅጣጫ ተቀይሯል" + "የስሜት ገላጭ ምስል ተለዋዋጭ መራጭ" + "%1$s እና %2$s" + "ጥላ" + "ነጣ ያለ የቆዳ ቀለም" + "መካከለኛ ነጣ ያለ የቆዳ ቀለም" + "መካከለኛ የቆዳ ቀለም" + "መካከለኛ ጠቆር ያለ የቆዳ ቀለም" + "ጠቆር ያለ የቆዳ ቀለም" + diff --git a/emojipicker/app/src/main/androidx/res/values-ar/strings.xml b/emojipicker/app/src/main/androidx/res/values-ar/strings.xml new file mode 100644 index 000000000..4d42ff9e9 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-ar/strings.xml @@ -0,0 +1,42 @@ + + + + + "المستخدمة حديثًا" + "الوجوه المبتسمة والرموز التعبيرية" + "الأشخاص" + "الحيوانات والطبيعة" + "المأكولات والمشروبات" + "السفر والأماكن" + "الأنشطة والأحداث" + "عناصر متنوعة" + "الرموز" + "الأعلام" + "لا تتوفر أي رموز تعبيرية." + "لم تستخدم أي رموز تعبيرية حتى الآن." + "مفتاح ثنائي الاتجاه للرموز التعبيرية" + "تم تغيير اتجاه الإيموجي" + "أداة اختيار الرموز التعبيرية" + "‏%1$s و%2$s" + "الظل" + "بشرة فاتحة" + "بشرة فاتحة متوسّطة" + "بشرة متوسّطة" + "بشرة داكنة متوسّطة" + "بشرة داكنة" + diff --git a/emojipicker/app/src/main/androidx/res/values-as/strings.xml b/emojipicker/app/src/main/androidx/res/values-as/strings.xml new file mode 100644 index 000000000..6ca5f5b7c --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-as/strings.xml @@ -0,0 +1,42 @@ + + + + + "অলপতে ব্যৱহৃত" + "স্মাইলী আৰু আৱেগ" + "মানুহ" + "পশু আৰু প্ৰকৃতি" + "খাদ্য আৰু পানীয়" + "ভ্ৰমণ আৰু স্থান" + "কাৰ্যকলাপ আৰু অনুষ্ঠান" + "বস্তু" + "চিহ্ন" + "পতাকা" + "কোনো ইম’জি উপলব্ধ নহয়" + "আপুনি এতিয়ালৈকে কোনো ইম’জি ব্যৱহাৰ কৰা নাই" + "ইম’জি বাইডাইৰেকশ্বনেল ছুইচ্চাৰ" + "দিক্-নিৰ্দেশনা প্ৰদৰ্শন কৰা ইম’জি সলনি কৰা হৈছে" + "ইম’জিৰ প্ৰকাৰ বাছনি কৰোঁতা" + "%1$s আৰু %2$s" + "ছাঁ" + "পাতলীয়া ছালৰ ৰং" + "মধ্যমীয়া পাতল ছালৰ ৰং" + "মিঠাবৰণীয়া ছালৰ ৰং" + "মধ্যমীয়া গাঢ় ছালৰ ৰং" + "গাঢ় ছালৰ ৰং" + diff --git a/emojipicker/app/src/main/androidx/res/values-az/strings.xml b/emojipicker/app/src/main/androidx/res/values-az/strings.xml new file mode 100644 index 000000000..c4c528575 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-az/strings.xml @@ -0,0 +1,42 @@ + + + + + "SON İSTİFADƏ EDİLƏN" + "SMAYLİK VƏ EMOSİYALAR" + "ADAMLAR" + "HEYVANLAR VƏ TƏBİƏT" + "QİDA VƏ İÇKİ" + "SƏYAHƏT VƏ MƏKANLAR" + "FƏALİYYƏTLƏR VƏ TƏDBİRLƏR" + "OBYEKTLƏR" + "SİMVOLLAR" + "BAYRAQLAR" + "Əlçatan emoji yoxdur" + "Hələ heç bir emojidən istifadə etməməsiniz" + "ikitərəfli emoji dəyişdirici" + "emoji istiqaməti dəyişdirildi" + "emoji variant seçicisi" + "%1$s və %2$s" + "kölgə" + "açıq dəri rəngi" + "orta açıq dəri rəngi" + "orta dəri rəngi" + "orta tünd dəri rəngi" + "tünd dəri rəngi" + diff --git a/emojipicker/app/src/main/androidx/res/values-b+sr+Latn/strings.xml b/emojipicker/app/src/main/androidx/res/values-b+sr+Latn/strings.xml new file mode 100644 index 000000000..8feb29612 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-b+sr+Latn/strings.xml @@ -0,0 +1,42 @@ + + + + + "NEDAVNO KORIŠĆENO" + "SMAJLIJI I EMOCIJE" + "LJUDI" + "ŽIVOTINJE I PRIRODA" + "HRANA I PIĆE" + "PUTOVANJA I MESTA" + "AKTIVNOSTI I DOGAĐAJI" + "OBJEKTI" + "SIMBOLI" + "ZASTAVE" + "Emodžiji nisu dostupni" + "Još niste koristili emodžije" + "dvosmerni prebacivač emodžija" + "smer emodžija je promenjen" + "birač varijanti emodžija" + "%1$s i %2$s" + "senka" + "koža svetle puti" + "koža srednjesvetle puti" + "koža srednje puti" + "koža srednjetamne puti" + "koža tamne puti" + diff --git a/emojipicker/app/src/main/androidx/res/values-be/strings.xml b/emojipicker/app/src/main/androidx/res/values-be/strings.xml new file mode 100644 index 000000000..67dc3c2e6 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-be/strings.xml @@ -0,0 +1,42 @@ + + + + + "НЯДАЎНА ВЫКАРЫСТАНЫЯ" + "СМАЙЛІКІ І ЭМОЦЫІ" + "ЛЮДЗІ" + "ЖЫВЁЛЫ І ПРЫРОДА" + "ЕЖА І НАПОІ" + "ПАДАРОЖЖЫ І МЕСЦЫ" + "ДЗЕЯННІ І ПАДЗЕІ" + "АБ\'ЕКТЫ" + "СІМВАЛЫ" + "СЦЯГІ" + "Няма даступных эмодзі" + "Вы пакуль не выкарыстоўвалі эмодзі" + "пераключальнік кірунку для эмодзі" + "кірунак арыентацыі эмодзі зменены" + "інструмент выбару варыянтаў эмодзі" + "%1$s і %2$s" + "цень" + "светлы колер скуры" + "умерана светлы колер скуры" + "нейтральны колер скуры" + "умерана цёмны колер скуры" + "цёмны колер скуры" + diff --git a/emojipicker/app/src/main/androidx/res/values-bg/strings.xml b/emojipicker/app/src/main/androidx/res/values-bg/strings.xml new file mode 100644 index 000000000..929d7676e --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-bg/strings.xml @@ -0,0 +1,42 @@ + + + + + "НАСКОРО ИЗПОЛЗВАНИ" + "ЕМОТИКОНИ И ЕМОЦИИ" + "ХОРА" + "ЖИВОТНИ И ПРИРОДА" + "ХРАНИ И НАПИТКИ" + "ПЪТУВАНИЯ И МЕСТА" + "АКТИВНОСТИ И СЪБИТИЯ" + "ПРЕДМЕТИ" + "СИМВОЛИ" + "ЗНАМЕНА" + "Няма налични емоджи" + "Все още не сте използвали емоджита" + "двупосочен превключвател на емоджи" + "посоката на емоджи бе променена" + "инструмент за избор на варианти за емоджи" + "%1$s и %2$s" + "сянка" + "светъл цвят на кожата" + "средно светъл цвят на кожата" + "междинен цвят на кожата" + "средно тъмен цвят на кожата" + "тъмен цвят на кожата" + diff --git a/emojipicker/app/src/main/androidx/res/values-bn/strings.xml b/emojipicker/app/src/main/androidx/res/values-bn/strings.xml new file mode 100644 index 000000000..55a691f28 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-bn/strings.xml @@ -0,0 +1,42 @@ + + + + + "সম্প্রতি ব্যবহার করা হয়েছে" + "স্মাইলি ও আবেগ" + "ব্যক্তি" + "প্রাণী ও প্রকৃতি" + "খাদ্য ও পানীয়" + "ভ্রমণ ও জায়গা" + "অ্যাক্টিভিটি ও ইভেন্ট" + "অবজেক্ট" + "প্রতীক" + "ফ্ল্যাগ" + "কোনও ইমোজি উপলভ্য নেই" + "আপনি এখনও কোনও ইমোজি ব্যবহার করেননি" + "ইমোজি দ্বিমুখী সুইচার" + "ইমোজির দিক পরিবর্তন হয়েছে" + "ইমোজি ভেরিয়েন্ট বাছাইকারী" + "%1$s এবং %2$s" + "ছায়া" + "হাল্কা স্কিন টোন" + "মাঝারি-হাল্কা স্কিন টোন" + "মাঝারি স্কিন টোন" + "মাঝারি-গাঢ় স্কিন টোন" + "গাঢ় স্কিন টোন" + diff --git a/emojipicker/app/src/main/androidx/res/values-bs/strings.xml b/emojipicker/app/src/main/androidx/res/values-bs/strings.xml new file mode 100644 index 000000000..401f6c827 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-bs/strings.xml @@ -0,0 +1,42 @@ + + + + + "NEDAVNO KORIŠTENO" + "SMAJLIJI I EMOCIJE" + "OSOBE" + "ŽIVOTINJE I PRIRODA" + "HRANA I PIĆE" + "PUTOVANJA I MJESTA" + "AKTIVNOSTI I DOGAĐAJI" + "PREDMETI" + "SIMBOLI" + "ZASTAVE" + "Emoji sličice nisu dostupne" + "Još niste koristili nijednu emoji sličicu" + "dvosmjerni prebacivač emodžija" + "emodži gleda u smjeru postavke prekidača" + "birač varijanti emodžija" + "%1$s i %2$s" + "sjenka" + "svijetla boja kože" + "srednje svijetla boja kože" + "srednja boja kože" + "srednje tamna boja kože" + "tamna boja kože" + diff --git a/emojipicker/app/src/main/androidx/res/values-ca/strings.xml b/emojipicker/app/src/main/androidx/res/values-ca/strings.xml new file mode 100644 index 000000000..09e2bc9a8 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-ca/strings.xml @@ -0,0 +1,42 @@ + + + + + "UTILITZATS FA POC" + "EMOTICONES I EMOCIONS" + "PERSONES" + "ANIMALS I NATURALESA" + "MENJAR I BEGUDA" + "VIATGES I LLOCS" + "ACTIVITATS I ESDEVENIMENTS" + "OBJECTES" + "SÍMBOLS" + "BANDERES" + "No hi ha cap emoji disponible" + "Encara no has fet servir cap emoji" + "selector bidireccional d\'emojis" + "s\'ha canviat la direcció de l\'emoji" + "selector de variants d\'emojis" + "%1$s i %2$s" + "ombra" + "to de pell clar" + "to de pell mitjà-clar" + "to de pell mitjà" + "to de pell mitjà-fosc" + "to de pell fosc" + diff --git a/emojipicker/app/src/main/androidx/res/values-cs/strings.xml b/emojipicker/app/src/main/androidx/res/values-cs/strings.xml new file mode 100644 index 000000000..8d7e0f502 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-cs/strings.xml @@ -0,0 +1,42 @@ + + + + + "NEDÁVNO POUŽITÉ" + "SMAJLÍCI A EMOCE" + "LIDÉ" + "ZVÍŘATA A PŘÍRODA" + "JÍDLO A PITÍ" + "CESTOVÁNÍ A MÍSTA" + "AKTIVITY A UDÁLOSTI" + "OBJEKTY" + "SYMBOLY" + "VLAJKY" + "Nejsou k dispozici žádné smajlíky" + "Zatím jste žádná emodži nepoužili" + "dvousměrný přepínač smajlíků" + "směr pohledu smajlíků přepnut" + "výběr variant emodži" + "%1$s a %2$s" + "stín" + "světlý tón pleti" + "středně světlý tón pleti" + "střední tón pleti" + "středně tmavý tón pleti" + "tmavý tón pleti" + diff --git a/emojipicker/app/src/main/androidx/res/values-da/strings.xml b/emojipicker/app/src/main/androidx/res/values-da/strings.xml new file mode 100644 index 000000000..e9eb67b95 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-da/strings.xml @@ -0,0 +1,42 @@ + + + + + "BRUGT FOR NYLIG" + "SMILEYS OG HUMØRIKONER" + "PERSONER" + "DYR OG NATUR" + "MAD OG DRIKKE" + "REJSER OG STEDER" + "AKTIVITETER OG BEGIVENHEDER" + "TING" + "SYMBOLER" + "FLAG" + "Der er ingen tilgængelige emojis" + "Du har ikke brugt nogen emojis endnu" + "tovejsskifter til emojis" + "emojien vender en anden retning" + "vælger for emojivariant" + "%1$s og %2$s" + "skygge" + "lys hudfarve" + "mellemlys hudfarve" + "medium hudfarve" + "mellemmørk hudfarve" + "mørk hudfarve" + diff --git a/emojipicker/app/src/main/androidx/res/values-de/strings.xml b/emojipicker/app/src/main/androidx/res/values-de/strings.xml new file mode 100644 index 000000000..6e72ab753 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-de/strings.xml @@ -0,0 +1,42 @@ + + + + + "ZULETZT VERWENDET" + "SMILEYS UND EMOTIONEN" + "PERSONEN" + "TIERE UND NATUR" + "ESSEN UND TRINKEN" + "REISEN UND ORTE" + "AKTIVITÄTEN UND EVENTS" + "OBJEKTE" + "SYMBOLE" + "FLAGGEN" + "Keine Emojis verfügbar" + "Du hast noch keine Emojis verwendet" + "Bidirektionale Emoji-Auswahl" + "Emoji-Richtung geändert" + "Emojivarianten-Auswahl" + "%1$s und %2$s" + "Hautton" + "Heller Hautton" + "Mittelheller Hautton" + "Mittlerer Hautton" + "Mitteldunkler Hautton" + "Dunkler Hautton" + diff --git a/emojipicker/app/src/main/androidx/res/values-el/strings.xml b/emojipicker/app/src/main/androidx/res/values-el/strings.xml new file mode 100644 index 000000000..4a59ed678 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-el/strings.xml @@ -0,0 +1,42 @@ + + + + + "ΧΡΗΣΙΜΟΠΟΙΗΘΗΚΑΝ ΠΡΟΣΦΑΤΑ" + "ΕΙΚΟΝΙΔΙΑ SMILEY ΚΑΙ ΣΥΝΑΙΣΘΗΜΑΤΑ" + "ΑΤΟΜΑ" + "ΖΩΑ ΚΑΙ ΦΥΣΗ" + "ΦΑΓΗΤΟ ΚΑΙ ΠΟΤΟ" + "ΤΑΞΙΔΙΑ ΚΑΙ ΜΕΡΗ" + "ΔΡΑΣΤΗΡΙΟΤΗΤΕΣ ΚΑΙ ΣΥΜΒΑΝΤΑ" + "ΑΝΤΙΚΕΙΜΕΝΑ" + "ΣΥΜΒΟΛΑ" + "ΣΗΜΑΙΕΣ" + "Δεν υπάρχουν διαθέσιμα emoji" + "Δεν έχετε χρησιμοποιήσει κανένα emoji ακόμα" + "αμφίδρομο στοιχείο εναλλαγής emoji" + "έγινε εναλλαγή της κατεύθυνσης που είναι στραμμένο το emoji" + "επιλογέας παραλλαγής emoji" + "%1$s και %2$s" + "σκιά" + "ανοιχτός τόνος επιδερμίδας" + "μεσαίος προς ανοιχτός τόνος επιδερμίδας" + "μεσαίος τόνος επιδερμίδας" + "μεσαίος προς σκούρος τόνος επιδερμίδας" + "σκούρος τόνος επιδερμίδας" + diff --git a/emojipicker/app/src/main/androidx/res/values-en-rAU/strings.xml b/emojipicker/app/src/main/androidx/res/values-en-rAU/strings.xml new file mode 100644 index 000000000..0b651f515 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-en-rAU/strings.xml @@ -0,0 +1,42 @@ + + + + + "RECENTLY USED" + "SMILEYS AND EMOTIONS" + "PEOPLE" + "ANIMALS AND NATURE" + "FOOD AND DRINK" + "TRAVEL AND PLACES" + "ACTIVITIES AND EVENTS" + "OBJECTS" + "SYMBOLS" + "FLAGS" + "No emojis available" + "You haven\'t used any emoji yet" + "emoji bidirectional switcher" + "emoji facing direction switched" + "emoji variant selector" + "%1$s and %2$s" + "shadow" + "light skin tone" + "medium-light skin tone" + "medium skin tone" + "medium-dark skin tone" + "dark skin tone" + diff --git a/emojipicker/app/src/main/androidx/res/values-en-rCA/strings.xml b/emojipicker/app/src/main/androidx/res/values-en-rCA/strings.xml new file mode 100644 index 000000000..d056590cc --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-en-rCA/strings.xml @@ -0,0 +1,42 @@ + + + + + "RECENTLY USED" + "SMILEYS AND EMOTIONS" + "PEOPLE" + "ANIMALS AND NATURE" + "FOOD AND DRINK" + "TRAVEL AND PLACES" + "ACTIVITIES AND EVENTS" + "OBJECTS" + "SYMBOLS" + "FLAGS" + "No emojis available" + "You haven\'t used any emojis yet" + "emoji bidirectional switcher" + "emoji facing direction switched" + "emoji variant selector" + "%1$s and %2$s" + "shadow" + "light skin tone" + "medium light skin tone" + "medium skin tone" + "medium dark skin tone" + "dark skin tone" + diff --git a/emojipicker/app/src/main/androidx/res/values-en-rGB/strings.xml b/emojipicker/app/src/main/androidx/res/values-en-rGB/strings.xml new file mode 100644 index 000000000..0b651f515 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-en-rGB/strings.xml @@ -0,0 +1,42 @@ + + + + + "RECENTLY USED" + "SMILEYS AND EMOTIONS" + "PEOPLE" + "ANIMALS AND NATURE" + "FOOD AND DRINK" + "TRAVEL AND PLACES" + "ACTIVITIES AND EVENTS" + "OBJECTS" + "SYMBOLS" + "FLAGS" + "No emojis available" + "You haven\'t used any emoji yet" + "emoji bidirectional switcher" + "emoji facing direction switched" + "emoji variant selector" + "%1$s and %2$s" + "shadow" + "light skin tone" + "medium-light skin tone" + "medium skin tone" + "medium-dark skin tone" + "dark skin tone" + diff --git a/emojipicker/app/src/main/androidx/res/values-en-rIN/strings.xml b/emojipicker/app/src/main/androidx/res/values-en-rIN/strings.xml new file mode 100644 index 000000000..0b651f515 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-en-rIN/strings.xml @@ -0,0 +1,42 @@ + + + + + "RECENTLY USED" + "SMILEYS AND EMOTIONS" + "PEOPLE" + "ANIMALS AND NATURE" + "FOOD AND DRINK" + "TRAVEL AND PLACES" + "ACTIVITIES AND EVENTS" + "OBJECTS" + "SYMBOLS" + "FLAGS" + "No emojis available" + "You haven\'t used any emoji yet" + "emoji bidirectional switcher" + "emoji facing direction switched" + "emoji variant selector" + "%1$s and %2$s" + "shadow" + "light skin tone" + "medium-light skin tone" + "medium skin tone" + "medium-dark skin tone" + "dark skin tone" + diff --git a/emojipicker/app/src/main/androidx/res/values-en-rXC/strings.xml b/emojipicker/app/src/main/androidx/res/values-en-rXC/strings.xml new file mode 100644 index 000000000..3e02185f4 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-en-rXC/strings.xml @@ -0,0 +1,42 @@ + + + + + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‏‏‏‏‎‏‏‎‏‎‎‎‏‏‎‏‎‏‎‏‏‏‏‏‎‏‏‎‏‏‎‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎‎‏‎‎‏‏‏‎RECENTLY USED‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‏‏‎‎‏‎‏‏‎‏‏‎‎‏‏‏‎‎‎‏‏‏‎‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‎‏‎‎‏‏‏‎‎‎‎‎‏‎SMILEYS AND EMOTIONS‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‎‏‎‎‏‎‏‎‎‎‏‏‎‏‏‏‎‏‎‏‏‎‏‏‏‏‏‎‎‎‏‏‎‏‎‏‎‏‏‏‏‎‏‎‏‎‏‏‎‎‎‏‎PEOPLE‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‎‎‏‏‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‏‎‏‎‎‏‏‏‎‎‏‎‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‎‎‏‎‏‎‏‎ANIMALS AND NATURE‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‎‎‎‎‏‎‎‎‏‏‎‎‏‎‏‎‏‎‏‎‎‏‎‎‏‎‏‎‎‏‏‏‏‎‎‎‎‏‏‏‎‏‎‏‏‎FOOD AND DRINK‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‏‏‎‏‎‎‏‎‎‏‎‎‎‏‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‎‎‎‏‏‎‎‎‎‎‎‎TRAVEL AND PLACES‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‏‎‎‏‏‏‎‏‎‏‏‎‎‏‎‏‏‎‎‏‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‎ACTIVITIES AND EVENTS‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‏‎‏‎‎‎‏‏‏‏‏‎‎‎‏‏‎‎‎‏‏‎‎‎‎‏‏‎‏‎‏‏‎‎‏‎‎‏‏‎‎‏‏‏‎‎‎‏‏‎OBJECTS‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‏‎‏‎‎‎‎‏‎‏‏‎‏‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‏‏‏‎‎‎‎‏‏‎‎‎‎‎‎‎‏‏‎‏‏‎SYMBOLS‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‎‏‏‏‏‏‎‎‏‏‏‎‎‏‎‏‏‎‏‏‎‎‎‎‎‏‎‎‏‎‏‏‎‎‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‏‎FLAGS‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‎‏‎‎‎‎‏‏‎‏‎‏‏‎‏‎‏‏‎‎‎‎‎‎‎‏‎‏‎‏‎‎‏‏‎‎‎‎‎‏‎‏‎‎‏‎‏‎‎‎‏‎No emojis available‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‎‎‎‏‎‎‎‎‏‏‎‏‏‎‎‏‏‏‎‎‎‎‏‎‎‎‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎‎‏‎‏‎‏‎‏‏‎‎‎‎You haven\'t used any emojis yet‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‏‎‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‎‎‏‏‏‏‎‏‎‏‏‏‎‏‎‎‏‎‏‎‎‎‎‏‎‏‎‎‎‏‏‏‏‎‏‎emoji bidirectional switcher‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‏‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‎‎‎‎‎‏‏‎emoji facing direction switched‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‎‏‏‏‏‎‏‎‏‎‏‏‎‏‎‎‎‏‎‎‏‎‎‏‎‎‎‏‏‎‏‎‏‎‎‏‏‎‎‎‎‎‎emoji variant selector‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‏‎‎‎‏‎‎‏‎‏‏‏‎‎‏‎‎‏‎‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‎‏‎‏‎‎‎‏‎‏‏‏‏‎‏‎‎‎‏‎%1$s and %2$s‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‏‏‎‏‏‎‎‎‏‏‏‎‎‎‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‏‎‏‎‎‏‏‏‏‎‎‎‎‏‏‏‎‏‎‏‏‎‎‎‎‎shadow‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‏‎‏‎‎‏‎‎‏‏‎‏‏‏‎‏‎‏‎‏‎‎‏‎‏‏‎‏‎‎‎‎‎‏‎‎‏‏‎‎‎‏‏‏‏‎‎‏‎‎‎‏‎light skin tone‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‏‎‎‏‎‎‏‏‏‎‎‎‎‎‏‏‏‏‏‏‎‎‏‏‎‏‏‎‎‎‎‎‏‏‎‎‏‎‏‎‏‏‎‏‏‎‏‏‎‏‎‏‎‎medium light skin tone‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‏‏‎‏‏‎‏‎‎‏‎‏‏‏‏‎‏‎‎‎‎‎‎‏‎‏‎‏‏‎‎‏‏‎‏‏‏‎‎‎‏‎‎‎‎‎‏‏‎medium skin tone‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‏‎‏‎‏‎‎‏‏‏‎‎‏‎‎‎‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‏‏‏‎‎‎‏‎‏‏‏‏‎‏‎‏‎‏‎‏‏‎‏‎medium dark skin tone‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‏‎‎‏‎‏‎‏‎‎‎‎‏‎‏‎‏‏‎‎‎‎‏‎‎‎‏‏‎‎‎‎‎‎‏‏‏‎‎‏‏‎‎‏‏‏‏‎‏‏‏‎‎dark skin tone‎‏‎‎‏‎" + diff --git a/emojipicker/app/src/main/androidx/res/values-es-rUS/strings.xml b/emojipicker/app/src/main/androidx/res/values-es-rUS/strings.xml new file mode 100644 index 000000000..e9001edfe --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-es-rUS/strings.xml @@ -0,0 +1,42 @@ + + + + + "USADOS RECIENTEMENTE" + "EMOTICONES Y EMOCIONES" + "PERSONAS" + "ANIMALES Y NATURALEZA" + "COMIDAS Y BEBIDAS" + "VIAJES Y LUGARES" + "ACTIVIDADES Y EVENTOS" + "OBJETOS" + "SÍMBOLOS" + "BANDERAS" + "No hay ningún emoji disponible" + "Todavía no usaste ningún emoji" + "selector bidireccional de emojis" + "se cambió la dirección del emoji" + "selector de variantes de emojis" + "%1$s y %2$s" + "sombra" + "tono de piel claro" + "tono de piel medio claro" + "tono de piel intermedio" + "tono de piel medio oscuro" + "tono de piel oscuro" + diff --git a/emojipicker/app/src/main/androidx/res/values-es/strings.xml b/emojipicker/app/src/main/androidx/res/values-es/strings.xml new file mode 100644 index 000000000..d2aed3688 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-es/strings.xml @@ -0,0 +1,42 @@ + + + + + "USADOS RECIENTEMENTE" + "EMOTICONOS Y EMOCIONES" + "PERSONAS" + "ANIMALES Y NATURALEZA" + "COMIDA Y BEBIDA" + "VIAJES Y SITIOS" + "ACTIVIDADES Y EVENTOS" + "OBJETOS" + "SÍMBOLOS" + "BANDERAS" + "No hay emojis disponibles" + "Aún no has usado ningún emoji" + "cambio bidireccional de emojis" + "dirección a la que se orienta el emoji cambiada" + "selector de variantes de emojis" + "%1$s y %2$s" + "sombra" + "tono de piel claro" + "tono de piel medio claro" + "tono de piel medio" + "tono de piel medio oscuro" + "tono de piel oscuro" + diff --git a/emojipicker/app/src/main/androidx/res/values-et/strings.xml b/emojipicker/app/src/main/androidx/res/values-et/strings.xml new file mode 100644 index 000000000..8b3d05aa9 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-et/strings.xml @@ -0,0 +1,42 @@ + + + + + "HILJUTI KASUTATUD" + "NÄOIKOONID JA EMOTSIOONID" + "INIMESED" + "LOOMAD JA LOODUS" + "SÖÖK JA JOOK" + "REISIMINE JA KOHAD" + "TEGEVUSED JA SÜNDMUSED" + "OBJEKTID" + "SÜMBOLID" + "LIPUD" + "Ühtegi emotikoni pole saadaval" + "Te pole veel ühtegi emotikoni kasutanud" + "emotikoni kahesuunaline lüliti" + "emotikoni suunda vahetati" + "emotikoni variandi valija" + "%1$s ja %2$s" + "vari" + "hele nahatoon" + "keskmiselt hele nahatoon" + "keskmine nahatoon" + "keskmiselt tume nahatoon" + "tume nahatoon" + diff --git a/emojipicker/app/src/main/androidx/res/values-eu/strings.xml b/emojipicker/app/src/main/androidx/res/values-eu/strings.xml new file mode 100644 index 000000000..9c550ca96 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-eu/strings.xml @@ -0,0 +1,42 @@ + + + + + "ERABILITAKO AZKENAK" + "AURPEGIERAK ETA ALDARTEAK" + "JENDEA" + "ANIMALIAK ETA NATURA" + "JAN-EDANAK" + "BIDAIAK ETA TOKIAK" + "JARDUERAK ETA GERTAERAK" + "OBJEKTUAK" + "IKURRAK" + "BANDERAK" + "Ez dago emotikonorik erabilgarri" + "Ez duzu erabili emojirik oraingoz" + "noranzko biko emoji-aldatzailea" + "emojiaren norabidea aldatu da" + "emojien aldaeren hautatzailea" + "%1$s eta %2$s" + "itzala" + "azalaren tonu argia" + "azalaren tonu argixka" + "azalaren tarteko tonua" + "azalaren tonu ilunxkoa" + "azalaren tonu iluna" + diff --git a/emojipicker/app/src/main/androidx/res/values-fa/strings.xml b/emojipicker/app/src/main/androidx/res/values-fa/strings.xml new file mode 100644 index 000000000..5930a4f02 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-fa/strings.xml @@ -0,0 +1,42 @@ + + + + + "اخیراً استفاده‌شده" + "شکلک‌ها و احساسات" + "افراد" + "حیوانات و طبیعت" + "غذا و نوشیدنی" + "سفر و مکان‌ها" + "فعالیت‌ها و رویدادها" + "اشیاء" + "نشان‌ها" + "پرچم‌ها" + "اموجی دردسترس نیست" + "هنوز از هیچ اموجی‌ای استفاده نکرده‌اید" + "تغییردهنده دوسویه اموجی" + "جهت چهره اموجی تغییر کرد" + "گزینشگر متغیر اموجی" + "‏%1$s و %2$s" + "سایه" + "رنگ‌مایه پوست روشن" + "رنگ‌مایه پوست ملایم روشن" + "رنگ‌مایه پوست ملایم" + "رنگ‌مایه پوست ملایم تیره" + "رنگ‌مایه پوست تیره" + diff --git a/emojipicker/app/src/main/androidx/res/values-fi/strings.xml b/emojipicker/app/src/main/androidx/res/values-fi/strings.xml new file mode 100644 index 000000000..bb6ccb586 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-fi/strings.xml @@ -0,0 +1,42 @@ + + + + + "VIIMEKSI KÄYTETYT" + "HYMIÖT JA TUNNETILAT" + "IHMISET" + "ELÄIMET JA LUONTO" + "RUOKA JA JUOMA" + "MATKAILU JA PAIKAT" + "AKTIVITEETIT JA TAPAHTUMAT" + "ESINEET" + "SYMBOLIT" + "LIPUT" + "Ei emojeita saatavilla" + "Et ole vielä käyttänyt emojeita" + "emoji kaksisuuntainen vaihtaja" + "emojin osoitussuunta vaihdettu" + "emojivalitsin" + "%1$s ja %2$s" + "varjostus" + "vaalea ihonväri" + "melko vaalea ihonväri" + "keskimääräinen ihonväri" + "melko tumma ihonväri" + "tumma ihonväri" + diff --git a/emojipicker/app/src/main/androidx/res/values-fr-rCA/strings.xml b/emojipicker/app/src/main/androidx/res/values-fr-rCA/strings.xml new file mode 100644 index 000000000..334f18f51 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-fr-rCA/strings.xml @@ -0,0 +1,42 @@ + + + + + "UTILISÉS RÉCEMMENT" + "ÉMOTICÔNES ET ÉMOTIONS" + "PERSONNES" + "ANIMAUX ET NATURE" + "ALIMENTS ET BOISSONS" + "VOYAGES ET LIEUX" + "ACTIVITÉS ET ÉVÉNEMENTS" + "OBJETS" + "SYMBOLES" + "DRAPEAUX" + "Aucun émoji proposé" + "Vous n\'avez encore utilisé aucun émoji" + "sélecteur bidirectionnel d\'émoji" + "Émoji tourné dans la direction inverse" + "sélecteur de variantes d\'émoji" + "%1$s et %2$s" + "ombre" + "teint clair" + "teint moyennement clair" + "teint moyen" + "teint moyennement foncé" + "teint foncé" + diff --git a/emojipicker/app/src/main/androidx/res/values-fr/strings.xml b/emojipicker/app/src/main/androidx/res/values-fr/strings.xml new file mode 100644 index 000000000..66f9f4d88 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-fr/strings.xml @@ -0,0 +1,42 @@ + + + + + "UTILISÉS RÉCEMMENT" + "ÉMOTICÔNES ET ÉMOTIONS" + "PERSONNES" + "ANIMAUX ET NATURE" + "ALIMENTATION ET BOISSONS" + "VOYAGES ET LIEUX" + "ACTIVITÉS ET ÉVÉNEMENTS" + "OBJETS" + "SYMBOLES" + "DRAPEAUX" + "Aucun emoji disponible" + "Vous n\'avez pas encore utilisé d\'emoji" + "sélecteur d\'emoji bidirectionnel" + "sens de l\'orientation de l\'emoji inversé" + "sélecteur de variante d\'emoji" + "%1$s et %2$s" + "ombre" + "teint clair" + "teint intermédiaire à clair" + "teint intermédiaire" + "teint intermédiaire à foncé" + "teint foncé" + diff --git a/emojipicker/app/src/main/androidx/res/values-gl/strings.xml b/emojipicker/app/src/main/androidx/res/values-gl/strings.xml new file mode 100644 index 000000000..f8715c36d --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-gl/strings.xml @@ -0,0 +1,42 @@ + + + + + "USADOS HAI POUCO" + "ICONAS XESTUAIS E EMOTICONAS" + "PERSOAS" + "ANIMAIS E NATUREZA" + "COMIDA E BEBIDA" + "VIAXES E LUGARES" + "ACTIVIDADES E EVENTOS" + "OBXECTOS" + "SÍMBOLOS" + "BANDEIRAS" + "Non hai ningún emoji dispoñible" + "Aínda non utilizaches ningún emoji" + "selector bidireccional de emojis" + "dirección do emoji cambiada" + "selector de variantes de emojis" + "%1$s e %2$s" + "sombra" + "ton de pel claro" + "ton de pel lixeiramente claro" + "ton de pel medio" + "ton de pel lixeiramente escuro" + "ton de pel escuro" + diff --git a/emojipicker/app/src/main/androidx/res/values-gu/strings.xml b/emojipicker/app/src/main/androidx/res/values-gu/strings.xml new file mode 100644 index 000000000..dad9fd387 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-gu/strings.xml @@ -0,0 +1,42 @@ + + + + + "તાજેતરમાં વપરાયેલું" + "સ્માઇલી અને મનોભાવો" + "લોકો" + "પ્રાણીઓ અને પ્રકૃતિ" + "ભોજન અને પીણાં" + "મુસાફરી અને સ્થળો" + "પ્રવૃત્તિઓ અને ઇવેન્ટ" + "ઑબ્જેક્ટ" + "પ્રતીકો" + "ઝંડા" + "કોઈ ઇમોજી ઉપલબ્ધ નથી" + "તમે હજી સુધી કોઈ ઇમોજીનો ઉપયોગ કર્યો નથી" + "બે દિશામાં સ્વિચ થઈ શકતું ઇમોજી સ્વિચર" + "ઇમોજીની દિશા બદલવામાં આવી" + "ઇમોજીનો પ્રકાર પસંદગીકર્તા" + "%1$s અને %2$s" + "શૅડો" + "ત્વચાનો હળવો ટોન" + "ત્વચાનો મધ્યમ હળવો ટોન" + "ત્વચાનો મધ્યમ ટોન" + "ત્વચાનો મધ્યમ ઘેરો ટોન" + "ત્વચાનો ઘેરો ટોન" + diff --git a/emojipicker/app/src/main/androidx/res/values-hi/strings.xml b/emojipicker/app/src/main/androidx/res/values-hi/strings.xml new file mode 100644 index 000000000..81cd653a3 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-hi/strings.xml @@ -0,0 +1,42 @@ + + + + + "हाल ही में इस्तेमाल किए गए" + "स्माइली और भावनाएं" + "लोग" + "जानवर और प्रकृति" + "खाने-पीने की चीज़ें" + "यात्रा और जगहें" + "गतिविधियां और इवेंट" + "ऑब्जेक्ट" + "सिंबल" + "झंडे" + "कोई इमोजी उपलब्ध नहीं है" + "आपने अब तक किसी भी इमोजी का इस्तेमाल नहीं किया है" + "दोनों तरफ़ ले जा सकने वाले स्विचर का इमोजी" + "इमोजी को फ़्लिप किया गया" + "इमोजी के वैरिएंट चुनने का टूल" + "%1$s और %2$s" + "शैडो" + "हल्के रंग की त्वचा" + "थोड़े हल्के रंग की त्वचा" + "सामान्य रंग की त्वचा" + "थोड़े गहरे रंग की त्वचा" + "गहरे रंग की त्वचा" + diff --git a/emojipicker/app/src/main/androidx/res/values-hr/strings.xml b/emojipicker/app/src/main/androidx/res/values-hr/strings.xml new file mode 100644 index 000000000..481b48673 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-hr/strings.xml @@ -0,0 +1,42 @@ + + + + + "NEDAVNO KORIŠTENO" + "SMAJLIĆI I EMOCIJE" + "OSOBE" + "ŽIVOTINJE I PRIRODA" + "HRANA I PIĆE" + "PUTOVANJA I MJESTA" + "AKTIVNOSTI I DOGAĐAJI" + "OBJEKTI" + "SIMBOLI" + "ZASTAVE" + "Nije dostupan nijedan emoji" + "Još niste upotrijebili emojije" + "dvosmjerni izmjenjivač emojija" + "promijenjen je smjer emojija" + "alat za odabir varijante emojija" + "%1$s i %2$s" + "sjena" + "svijetla boja kože" + "srednje svijetla boja kože" + "srednja boja kože" + "srednje tamna boja kože" + "tamna boja kože" + diff --git a/emojipicker/app/src/main/androidx/res/values-hu/strings.xml b/emojipicker/app/src/main/androidx/res/values-hu/strings.xml new file mode 100644 index 000000000..d048746c7 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-hu/strings.xml @@ -0,0 +1,42 @@ + + + + + "LEGUTÓBB HASZNÁLT" + "HANGULATJELEK ÉS HANGULATOK" + "SZEMÉLYEK" + "ÁLLATOK ÉS TERMÉSZET" + "ÉTEL ÉS ITAL" + "UTAZÁS ÉS HELYEK" + "TEVÉKENYSÉGEK ÉS ESEMÉNYEK" + "TÁRGYAK" + "SZIMBÓLUMOK" + "ZÁSZLÓK" + "Nincsenek rendelkezésre álló emojik" + "Még nem használt emojikat" + "kétirányú emojiváltó" + "módosítva lett, hogy merre nézzen az emoji" + "emojiváltozat-választó" + "%1$s és %2$s" + "árnyék" + "világos bőrtónus" + "közepesen világos bőrtónus" + "közepes bőrtónus" + "közepesen sötét bőrtónus" + "sötét bőrtónus" + diff --git a/emojipicker/app/src/main/androidx/res/values-hy/strings.xml b/emojipicker/app/src/main/androidx/res/values-hy/strings.xml new file mode 100644 index 000000000..be551decf --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-hy/strings.xml @@ -0,0 +1,42 @@ + + + + + "ՎԵՐՋԵՐՍ ՕԳՏԱԳՈՐԾՎԱԾ" + "ԶՄԱՅԼԻԿՆԵՐ ԵՎ ՀՈՒԶԱՊԱՏԿԵՐԱԿՆԵՐ" + "ՄԱՐԴԻԿ" + "ԿԵՆԴԱՆԻՆԵՐ ԵՎ ԲՆՈՒԹՅՈՒՆ" + "ՍՆՈՒՆԴ ԵՎ ԽՄԻՉՔ" + "ՃԱՄՓՈՐԴՈՒԹՅՈՒՆ ԵՎ ՏԵՍԱՐԺԱՆ ՎԱՅՐԵՐ" + "ԺԱՄԱՆՑ ԵՎ ՄԻՋՈՑԱՌՈՒՄՆԵՐ" + "ԱՌԱՐԿԱՆԵՐ" + "ՆՇԱՆՆԵՐ" + "ԴՐՈՇՆԵՐ" + "Հասանելի էմոջիներ չկան" + "Դուք դեռ չեք օգտագործել էմոջիներ" + "էմոջիների երկկողմանի փոխանջատիչ" + "էմոջիի դեմքի ուղղությունը փոխվեց" + "էմոջիների տարբերակի ընտրիչ" + "%1$s և %2$s" + "ստվեր" + "մաշկի բաց երանգ" + "մաշկի չափավոր բաց երանգ" + "մաշկի չեզոք երանգ" + "մաշկի չափավոր մուգ երանգ" + "մաշկի մուգ երանգ" + diff --git a/emojipicker/app/src/main/androidx/res/values-in/strings.xml b/emojipicker/app/src/main/androidx/res/values-in/strings.xml new file mode 100644 index 000000000..09703b727 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-in/strings.xml @@ -0,0 +1,42 @@ + + + + + "TERAKHIR DIGUNAKAN" + "SMILEY DAN EMOTIKON" + "ORANG" + "HEWAN DAN ALAM" + "MAKANAN DAN MINUMAN" + "WISATA DAN TEMPAT" + "AKTIVITAS DAN ACARA" + "OBJEK" + "SIMBOL" + "BENDERA" + "Tidak ada emoji yang tersedia" + "Anda belum menggunakan emoji apa pun" + "pengalih dua arah emoji" + "arah hadap emoji dialihkan" + "pemilih varian emoji" + "%1$s dan %2$s" + "bayangan" + "warna kulit cerah" + "warna kulit kuning langsat" + "warna kulit sawo matang" + "warna kulit cokelat" + "warna kulit gelap" + diff --git a/emojipicker/app/src/main/androidx/res/values-is/strings.xml b/emojipicker/app/src/main/androidx/res/values-is/strings.xml new file mode 100644 index 000000000..691d3c623 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-is/strings.xml @@ -0,0 +1,42 @@ + + + + + "NOTAÐ NÝLEGA" + "BROSKARLAR OG TILFINNINGAR" + "FÓLK" + "DÝR OG NÁTTÚRA" + "MATUR OG DRYKKUR" + "FERÐALÖG OG STAÐIR" + "VIRKNI OG VIÐBURÐIR" + "HLUTIR" + "TÁKN" + "FÁNAR" + "Engin emoji-tákn í boði" + "Þú hefur ekki notað nein emoji enn" + "emoji-val í báðar áttir" + "Áttinni sem emoji snýr að hefur verið breytt" + "val emoji-afbrigðis" + "%1$s og %2$s" + "skuggi" + "ljós húðlitur" + "meðalljós húðlitur" + "húðlitur í meðallagi" + "meðaldökkur húðlitur" + "dökkur húðlitur" + diff --git a/emojipicker/app/src/main/androidx/res/values-it/strings.xml b/emojipicker/app/src/main/androidx/res/values-it/strings.xml new file mode 100644 index 000000000..6ff2bf9c2 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-it/strings.xml @@ -0,0 +1,42 @@ + + + + + "USATE DI RECENTE" + "SMILE ED EMOZIONI" + "PERSONE" + "ANIMALI E NATURA" + "CIBO E BEVANDE" + "VIAGGI E LUOGHI" + "ATTIVITÀ ED EVENTI" + "OGGETTI" + "SIMBOLI" + "BANDIERE" + "Nessuna emoji disponibile" + "Non hai ancora usato alcuna emoji" + "selettore bidirezionale di emoji" + "emoji sottosopra" + "selettore variante emoji" + "%1$s e %2$s" + "ombra" + "carnagione chiara" + "carnagione medio-chiara" + "carnagione media" + "carnagione medio-scura" + "carnagione scura" + diff --git a/emojipicker/app/src/main/androidx/res/values-iw/strings.xml b/emojipicker/app/src/main/androidx/res/values-iw/strings.xml new file mode 100644 index 000000000..7a8eae8a7 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-iw/strings.xml @@ -0,0 +1,42 @@ + + + + + "בשימוש לאחרונה" + "סמיילי ואמוטיקונים" + "אנשים" + "בעלי חיים וטבע" + "מזון ומשקאות" + "נסיעות ומקומות" + "פעילויות ואירועים" + "אובייקטים" + "סמלים" + "דגלים" + "אין סמלי אמוג\'י זמינים" + "עדיין לא השתמשת באף אמוג\'י" + "לחצן דו-כיווני למעבר לאמוג\'י" + "מתג נגישות להחלפת הכיוון של האמוג\'י" + "בורר של סוגי אמוג\'י" + "‏%1$s ו-%2$s" + "צל" + "גוון עור בהיר" + "גוון עור בינוני-בהיר" + "גוון עור בינוני" + "גוון עור בינוני-כהה" + "גוון עור כהה" + diff --git a/emojipicker/app/src/main/androidx/res/values-ja/strings.xml b/emojipicker/app/src/main/androidx/res/values-ja/strings.xml new file mode 100644 index 000000000..395ee6d73 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-ja/strings.xml @@ -0,0 +1,42 @@ + + + + + "最近使用した絵文字" + "顔文字、気分" + "人物" + "動物、自然" + "食べ物、飲み物" + "移動、場所" + "活動、イベント" + "アイテム" + "記号" + "旗" + "使用できる絵文字がありません" + "まだ絵文字を使用していません" + "絵文字の双方向切り替え" + "絵文字の向きを切り替えました" + "絵文字バリエーション セレクタ" + "%1$s、%2$s" + "シャドウ" + "明るい肌の色" + "やや明るい肌の色" + "中間の明るさの肌の色" + "やや濃い肌の色" + "濃い肌の色" + diff --git a/emojipicker/app/src/main/androidx/res/values-ka/strings.xml b/emojipicker/app/src/main/androidx/res/values-ka/strings.xml new file mode 100644 index 000000000..5d23faa22 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-ka/strings.xml @@ -0,0 +1,42 @@ + + + + + "ბოლო დროს გამოყენებული" + "სიცილაკები და ემოციები" + "ადამიანები" + "ცხოველები და ბუნება" + "საჭმელი და სასმელი" + "მოგზაურობა და ადგილები" + "აქტივობები და მოვლენები" + "ობიექტები" + "სიმბოლოები" + "დროშები" + "Emoji-ები მიუწვდომელია" + "Emoji-ებით ჯერ არ გისარგებლიათ" + "emoji-ს ორმიმართულებიანი გადამრთველი" + "emoji-ის მიმართულება შეცვლილია" + "emoji-ს ვარიანტის ამომრჩევი" + "%1$s და %2$s" + "ჩრდილი" + "კანის ღია ტონი" + "კანის ღია საშუალო ტონი" + "კანის საშუალო ტონი" + "კანის მუქი საშუალო ტონი" + "კანის მუქი ტონი" + diff --git a/emojipicker/app/src/main/androidx/res/values-kk/strings.xml b/emojipicker/app/src/main/androidx/res/values-kk/strings.xml new file mode 100644 index 000000000..cd6a8c571 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-kk/strings.xml @@ -0,0 +1,42 @@ + + + + + "СОҢҒЫ ҚОЛДАНЫЛҒАНДАР" + "СМАЙЛДАР МЕН ЭМОЦИЯЛАР" + "АДАМДАР" + "ЖАНУАРЛАР ЖӘНЕ ТАБИҒАТ" + "ТАМАҚ ПЕН СУСЫН" + "САЯХАТ ЖӘНЕ ОРЫНДАР" + "ӘРЕКЕТТЕР МЕН ІС-ШАРАЛАР" + "НЫСАНДАР" + "ТАҢБАЛАР" + "ЖАЛАУШАЛАР" + "Эмоджи жоқ" + "Әлі ешқандай эмоджи пайдаланылған жоқ." + "екіжақты эмоджи ауыстырғыш" + "эмоджи бағыты ауыстырылды" + "эмоджи нұсқаларын таңдау құралы" + "%1$s және %2$s" + "көлеңке" + "терінің ақшыл реңі" + "терінің орташа ақшыл реңі" + "терінің орташа реңі" + "терінің орташа қараторы реңі" + "терінің қараторы реңі" + diff --git a/emojipicker/app/src/main/androidx/res/values-km/strings.xml b/emojipicker/app/src/main/androidx/res/values-km/strings.xml new file mode 100644 index 000000000..0b4dffc20 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-km/strings.xml @@ -0,0 +1,42 @@ + + + + + "បាន​ប្រើ​ថ្មីៗ​នេះ" + "រូប​ទឹក​មុខ និងអារម្មណ៍" + "មនុស្ស" + "សត្វ និងធម្មជាតិ" + "អាហារ និងភេសជ្ជៈ" + "ការធ្វើដំណើរ និងទីកន្លែង" + "សកម្មភាព និងព្រឹត្តិការណ៍" + "វត្ថុ" + "និមិត្តសញ្ញា" + "ទង់" + "មិនមាន​រូប​អារម្មណ៍ទេ" + "អ្នក​មិនទាន់​បានប្រើរូប​អារម្មណ៍​ណាមួយ​នៅឡើយទេ" + "មុខងារប្ដូរទ្វេទិសនៃរូប​អារម្មណ៍" + "បានប្ដូរទិសដៅបែររបស់រូប​អារម្មណ៍" + "ផ្ទាំងជ្រើសរើសជម្រើសរូប​អារម្មណ៍" + "%1$s និង %2$s" + "ស្រមោល" + "សម្បុរស្បែក​ស" + "សម្បុរស្បែក​សល្មម" + "សម្បុរ​ស្បែក​ល្មម" + "សម្បុរ​ស្បែកខ្មៅល្មម" + "សម្បុរ​ស្បែក​ខ្មៅ" + diff --git a/emojipicker/app/src/main/androidx/res/values-kn/strings.xml b/emojipicker/app/src/main/androidx/res/values-kn/strings.xml new file mode 100644 index 000000000..b05a64c2c --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-kn/strings.xml @@ -0,0 +1,42 @@ + + + + + "ಇತ್ತೀಚೆಗೆ ಬಳಸಿರುವುದು" + "ಸ್ಮೈಲಿಗಳು ಮತ್ತು ಭಾವನೆಗಳು" + "ಜನರು" + "ಪ್ರಾಣಿಗಳು ಮತ್ತು ಪ್ರಕೃತಿ" + "ಆಹಾರ ಮತ್ತು ಪಾನೀಯ" + "ಪ್ರಯಾಣ ಮತ್ತು ಸ್ಥಳಗಳು" + "ಚಟುವಟಿಕೆಗಳು ಮತ್ತು ಈವೆಂಟ್‌ಗಳು" + "ವಸ್ತುಗಳು" + "ಸಂಕೇತಗಳು" + "ಫ್ಲ್ಯಾಗ್‌ಗಳು" + "ಯಾವುದೇ ಎಮೊಜಿಗಳು ಲಭ್ಯವಿಲ್ಲ" + "ನೀವು ಇನ್ನೂ ಯಾವುದೇ ಎಮೋಜಿಗಳನ್ನು ಬಳಸಿಲ್ಲ" + "ಎಮೋಜಿ ಬೈಡೈರೆಕ್ಷನಲ್ ಸ್ವಿಚರ್" + "ಎಮೋಜಿ ಎದುರಿಸುತ್ತಿರುವ ದಿಕ್ಕನ್ನು ಬದಲಾಯಿಸಲಾಗಿದೆ" + "ಎಮೋಜಿ ವೇರಿಯಂಟ್ ಸೆಲೆಕ್ಟರ್" + "%1$s ಮತ್ತು %2$s" + "ನೆರಳು" + "ಲೈಟ್ ಸ್ಕಿನ್ ಟೋನ್" + "ಮೀಡಿಯಮ್ ಲೈಟ್ ಸ್ಕಿನ್ ಟೋನ್" + "ಮೀಡಿಯಮ್ ಸ್ಕಿನ್ ಟೋನ್" + "ಮೀಡಿಯಮ್ ಡಾರ್ಕ್ ಸ್ಕಿನ್ ಟೋನ್" + "ಡಾರ್ಕ್ ಸ್ಕಿನ್ ಟೋನ್" + diff --git a/emojipicker/app/src/main/androidx/res/values-ko/strings.xml b/emojipicker/app/src/main/androidx/res/values-ko/strings.xml new file mode 100644 index 000000000..22cace838 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-ko/strings.xml @@ -0,0 +1,42 @@ + + + + + "최근 사용" + "이모티콘 및 감정" + "사람" + "동물 및 자연" + "식음료" + "여행 및 장소" + "활동 및 이벤트" + "사물" + "기호" + "깃발" + "사용 가능한 그림 이모티콘 없음" + "아직 사용한 이모티콘이 없습니다." + "그림 이모티콘 양방향 전환기" + "이모티콘 방향 전환됨" + "그림 이모티콘 옵션 선택기" + "%1$s 및 %2$s" + "그림자" + "밝은 피부색" + "약간 밝은 피부색" + "중간 피부색" + "약간 어두운 피부색" + "어두운 피부색" + diff --git a/emojipicker/app/src/main/androidx/res/values-ky/strings.xml b/emojipicker/app/src/main/androidx/res/values-ky/strings.xml new file mode 100644 index 000000000..aa3454690 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-ky/strings.xml @@ -0,0 +1,42 @@ + + + + + "АКЫРКЫ КОЛДОНУЛГАНДАР" + "БЫЙТЫКЧАЛАР ЖАНА ЭМОЦИЯЛАР" + "АДАМДАР" + "ЖАНЫБАРЛАР ЖАНА ЖАРАТЫЛЫШ" + "АЗЫК-ТҮЛҮК ЖАНА СУУСУНДУКТАР" + "САЯКАТ ЖАНА ЖЕРЛЕР" + "ИШ-АРАКЕТТЕР ЖАНА ИШ-ЧАРАЛАР" + "ОБЪЕКТТЕР" + "СИМВОЛДОР" + "ЖЕЛЕКТЕР" + "Жеткиликтүү быйтыкчалар жок" + "Бир да быйтыкча колдоно элексиз" + "эки тараптуу быйтыкча которгуч" + "быйтыкчанын багыты которулду" + "быйтыкча тандагыч" + "%1$s жана %2$s" + "көлөкө" + "ачык түстүү тери" + "агыраак түстүү тери" + "орточо түстүү тери" + "орточо кара тору түстүү тери" + "кара тору түстүү тери" + diff --git a/emojipicker/app/src/main/androidx/res/values-lo/strings.xml b/emojipicker/app/src/main/androidx/res/values-lo/strings.xml new file mode 100644 index 000000000..174400e08 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-lo/strings.xml @@ -0,0 +1,42 @@ + + + + + "ໃຊ້ຫຼ້າສຸດ" + "ໜ້າຍິ້ມ ແລະ ຄວາມຮູ້ສຶກ" + "ຜູ້ຄົນ" + "ສັດ ແລະ ທຳມະຊາດ" + "ອາຫານ ແລະ ເຄື່ອງດື່ມ" + "ການເດີນທາງ ແລະ ສະຖານທີ່" + "ການເຄື່ອນໄຫວ ແລະ ກິດຈະກຳ" + "ວັດຖຸ" + "ສັນຍາລັກ" + "ທຸງ" + "ບໍ່ມີອີໂມຈິໃຫ້ນຳໃຊ້" + "ທ່ານຍັງບໍ່ໄດ້ໃຊ້ອີໂມຈິໃດເທື່ອ" + "ຕົວສະຫຼັບອີໂມຈິແບບ 2 ທິດທາງ" + "ປ່ຽນທິດທາງການຫັນໜ້າຂອງອີໂມຈິແລ້ວ" + "ຕົວເລືອກຕົວແປອີໂມຈິ" + "%1$s ແລະ %2$s" + "ເງົາ" + "ສະກິນໂທນແຈ້ງ" + "ສະກິນໂທນແຈ້ງປານກາງ" + "ສະກິນໂທນປານກາງ" + "ສະກິນໂທນມືດປານກາງ" + "ສະກິນໂທນມືດ" + diff --git a/emojipicker/app/src/main/androidx/res/values-lt/strings.xml b/emojipicker/app/src/main/androidx/res/values-lt/strings.xml new file mode 100644 index 000000000..72390ae43 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-lt/strings.xml @@ -0,0 +1,42 @@ + + + + + "NESENIAI NAUDOTI" + "JAUSTUKAI IR EMOCIJOS" + "ŽMONĖS" + "GYVŪNAI IR GAMTA" + "MAISTAS IR GĖRIMAI" + "KELIONĖS IR VIETOS" + "VEIKLA IR ĮVYKIAI" + "OBJEKTAI" + "SIMBOLIAI" + "VĖLIAVOS" + "Nėra jokių pasiekiamų jaustukų" + "Dar nenaudojote jokių jaustukų" + "dvikryptis jaustukų perjungikli" + "perjungta jaustukų nuoroda" + "jaustuko varianto parinkiklis" + "%1$s ir %2$s" + "šešėlis" + "šviesi odos spalva" + "vidutiniškai šviesi odos spalva" + "nei tamsi, nei šviesi odos spalva" + "vidutiniškai tamsi odos spalva" + "tamsi odos spalva" + diff --git a/emojipicker/app/src/main/androidx/res/values-lv/strings.xml b/emojipicker/app/src/main/androidx/res/values-lv/strings.xml new file mode 100644 index 000000000..0fe66ac75 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-lv/strings.xml @@ -0,0 +1,42 @@ + + + + + "NESEN LIETOTAS" + "SMAIDIŅI UN EMOCIJAS" + "PERSONAS" + "DZĪVNIEKI UN DABA" + "ĒDIENI UN DZĒRIENI" + "CEĻOJUMI UN VIETAS" + "PASĀKUMI UN NOTIKUMI" + "OBJEKTI" + "SIMBOLI" + "KAROGI" + "Nav pieejamu emocijzīmju" + "Jūs vēl neesat izmantojis nevienu emocijzīmi" + "emocijzīmju divvirzienu pārslēdzējs" + "mainīts emocijzīmes virziens" + "emocijzīmes varianta atlasītājs" + "%1$s un %2$s" + "ēna" + "gaišs ādas tonis" + "vidēji gaišs ādas tonis" + "vidējs ādas tonis" + "vidēji tumšs ādas tonis" + "tumšs ādas tonis" + diff --git a/emojipicker/app/src/main/androidx/res/values-mk/strings.xml b/emojipicker/app/src/main/androidx/res/values-mk/strings.xml new file mode 100644 index 000000000..b7ceab0f4 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-mk/strings.xml @@ -0,0 +1,42 @@ + + + + + "НЕОДАМНА КОРИСТЕНИ" + "СМЕШКОВЦИ И ЕМОЦИИ" + "ЛУЃЕ" + "ЖИВОТНИ И ПРИРОДА" + "ХРАНА И ПИЈАЛАЦИ" + "ПАТУВАЊЕ И МЕСТА" + "АКТИВНОСТИ И НАСТАНИ" + "ОБЈЕКТИ" + "СИМБОЛИ" + "ЗНАМИЊА" + "Нема достапни емоџија" + "Сѐ уште не сте користеле емоџија" + "двонасочен менувач на емоџија" + "насоката во којашто е свртено емоџито е сменета" + "избирач на варијанти на емоџија" + "%1$s и %2$s" + "сенка" + "светол тон на кожата" + "средно светол тон на кожата" + "среден тон на кожата" + "средно темен тон на кожата" + "темен тон на кожата" + diff --git a/emojipicker/app/src/main/androidx/res/values-ml/strings.xml b/emojipicker/app/src/main/androidx/res/values-ml/strings.xml new file mode 100644 index 000000000..60b985701 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-ml/strings.xml @@ -0,0 +1,42 @@ + + + + + "അടുത്തിടെ ഉപയോഗിച്ചവ" + "സ്മൈലികളും ഇമോഷനുകളും" + "ആളുകൾ" + "മൃഗങ്ങളും പ്രകൃതിയും" + "ഭക്ഷണപാനീയങ്ങൾ" + "യാത്രയും സ്ഥലങ്ങളും" + "ആക്‌റ്റിവിറ്റികളും ഇവന്റുകളും" + "വസ്‌തുക്കൾ" + "ചിഹ്നങ്ങൾ" + "പതാകകൾ" + "ഇമോജികളൊന്നും ലഭ്യമല്ല" + "നിങ്ങൾ ഇതുവരെ ഇമോജികളൊന്നും ഉപയോഗിച്ചിട്ടില്ല" + "ഇമോജി ദ്വിദിശ സ്വിച്ചർ" + "ഇമോജിയുടെ ദിശ മാറ്റി" + "ഇമോജി വേരിയന്റ് സെലക്‌ടർ" + "%1$s, %2$s" + "ഷാഡോ" + "ലൈറ്റ് സ്‌കിൻ ടോൺ" + "മീഡിയം ലൈറ്റ് സ്‌കിൻ ടോൺ" + "മീഡിയം സ്‌കിൻ ടോൺ" + "മീഡിയം ഡാർക്ക് സ്‌കിൻ ടോൺ" + "ഡാർക്ക് സ്‌കിൻ ടോൺ" + diff --git a/emojipicker/app/src/main/androidx/res/values-mn/strings.xml b/emojipicker/app/src/main/androidx/res/values-mn/strings.xml new file mode 100644 index 000000000..6b07ea5ae --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-mn/strings.xml @@ -0,0 +1,42 @@ + + + + + "САЯХАН АШИГЛАСАН" + "ИНЭЭМСЭГЛЭЛ БОЛОН СЭТГЭЛ ХӨДЛӨЛ" + "ХҮМҮҮС" + "АМЬТАД БА БАЙГАЛЬ" + "ХООЛ БОЛОН УУХ ЗҮЙЛ" + "АЯЛАЛ БОЛОН ГАЗРУУД" + "ҮЙЛ АЖИЛЛАГАА БОЛОН АРГА ХЭМЖЭЭ" + "ОБЪЕКТ" + "ТЭМДЭГ" + "ТУГ" + "Боломжтой эможи алга" + "Та ямар нэгэн эможи ашиглаагүй байна" + "эможигийн хоёр чиглэлтэй сэлгүүр" + "эможигийн харж буй чиглэлийг сэлгэсэн" + "эможигийн хувилбар сонгогч" + "%1$s болон %2$s" + "сүүдэр" + "цайвар арьсны өнгө" + "дунд зэргийн цайвар арьсны өнгө" + "дунд зэргийн арьсны өнгө" + "дунд зэргийн бараан арьсны өнгө" + "бараан арьсны өнгө" + diff --git a/emojipicker/app/src/main/androidx/res/values-mr/strings.xml b/emojipicker/app/src/main/androidx/res/values-mr/strings.xml new file mode 100644 index 000000000..316b2c485 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-mr/strings.xml @@ -0,0 +1,42 @@ + + + + + "अलीकडे वापरलेला" + "स्मायली आणि भावना" + "लोक" + "प्राणी आणि निसर्ग" + "खाद्यपदार्थ आणि पेय" + "प्रवास आणि ठिकाणे" + "ॲक्टिव्हिटी आणि इव्हेंट" + "ऑब्जेक्ट" + "चिन्हे" + "ध्वज" + "कोणतेही इमोजी उपलब्ध नाहीत" + "तुम्ही अद्याप कोणतेही इमोजी वापरलेले नाहीत" + "इमोजीचा द्विदिश स्विचर" + "दिशा दाखवणारा इमोजी स्विच केला" + "इमोजी व्हेरीयंट सिलेक्टर" + "%1$s आणि %2$s" + "शॅडो" + "उजळ रंगाची त्वचा" + "मध्यम उजळ रंगाची त्वचा" + "मध्यम रंगाची त्वचा" + "मध्यम गडद रंगाची त्वचा" + "गडद रंगाची त्वचा" + diff --git a/emojipicker/app/src/main/androidx/res/values-ms/strings.xml b/emojipicker/app/src/main/androidx/res/values-ms/strings.xml new file mode 100644 index 000000000..d5ecef2db --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-ms/strings.xml @@ -0,0 +1,42 @@ + + + + + "DIGUNAKAN BARU-BARU INI" + "SMILEY DAN EMOSI" + "ORANG" + "HAIWAN DAN ALAM SEMULA JADI" + "MAKANAN DAN MINUMAN" + "PERJALANAN DAN TEMPAT" + "AKTIVITI DAN ACARA" + "OBJEK" + "SIMBOL" + "BENDERA" + "Tiada emoji tersedia" + "Anda belum menggunakan mana-mana emoji lagi" + "penukar dwiarah emoji" + "emoji menghadap arah ditukar" + "pemilih varian emoji" + "%1$s dan %2$s" + "bebayang" + "ton kulit cerah" + "ton kulit sederhana cerah" + "ton kulit sederhana" + "ton kulit sederhana gelap" + "ton kulit gelap" + diff --git a/emojipicker/app/src/main/androidx/res/values-my/strings.xml b/emojipicker/app/src/main/androidx/res/values-my/strings.xml new file mode 100644 index 000000000..99fb7ff2a --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-my/strings.xml @@ -0,0 +1,42 @@ + + + + + "မကြာသေးမီက သုံးထားသည်များ" + "စမိုင်းလီနှင့် ခံစားချက်များ" + "လူများ" + "တိရစ္ဆာန်များနှင့် သဘာဝ" + "အစားအသောက်" + "ခရီးသွားခြင်းနှင့် အရပ်ဒေသများ" + "လုပ်ဆောင်ချက်နှင့် အစီအစဉ်များ" + "အရာဝတ္ထုများ" + "သင်္ကေတများ" + "အလံများ" + "အီမိုဂျီ မရနိုင်ပါ" + "အီမိုဂျီ အသုံးမပြုသေးပါ" + "အီမိုဂျီ လမ်းကြောင်းနှစ်ခုပြောင်းစနစ်" + "အီမိုဂျီလှည့်သောဘက်ကို ပြောင်းထားသည်" + "အီမိုဂျီမူကွဲ ရွေးချယ်စနစ်" + "%1$s နှင့် %2$s" + "အရိပ်" + "ဖြူသည့် အသားအရောင်" + "အနည်းငယ်ဖြူသည့် အသားအရောင်" + "အလယ်အလတ် အသားအရောင်" + "အနည်းငယ်ညိုသည့် အသားအရောင်" + "ညိုသည့် အသားအရောင်" + diff --git a/emojipicker/app/src/main/androidx/res/values-nb/strings.xml b/emojipicker/app/src/main/androidx/res/values-nb/strings.xml new file mode 100644 index 000000000..368ef416b --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-nb/strings.xml @@ -0,0 +1,42 @@ + + + + + "NYLIG BRUKT" + "SMILEFJES OG UTTRYKKSIKONER" + "PERSONER" + "DYR OG NATUR" + "MAT OG DRIKKE" + "REISE OG STEDER" + "AKTIVITETER OG ARRANGEMENTER" + "GJENSTANDER" + "SYMBOLER" + "FLAGG" + "Ingen emojier er tilgjengelige" + "Du har ikke brukt noen emojier ennå" + "toveisvelger for emoji" + "emojiretningen er slått på" + "velger for emojivariant" + "%1$s og %2$s" + "skygge" + "lys hudtone" + "middels lys hudtone" + "middels hudtone" + "middels mørk hudtone" + "mørk hudtone" + diff --git a/emojipicker/app/src/main/androidx/res/values-ne/strings.xml b/emojipicker/app/src/main/androidx/res/values-ne/strings.xml new file mode 100644 index 000000000..50a489be6 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-ne/strings.xml @@ -0,0 +1,42 @@ + + + + + "हालसालै प्रयोग गरिएको" + "स्माइली र भावनाहरू" + "मान्छेहरू" + "पशु र प्रकृति" + "खाद्य तथा पेय पदार्थ" + "यात्रा र ठाउँहरू" + "क्रियाकलाप तथा कार्यक्रमहरू" + "वस्तुहरू" + "चिन्हहरू" + "झन्डाहरू" + "कुनै पनि इमोजी उपलब्ध छैन" + "तपाईंले हालसम्म कुनै पनि इमोजी प्रयोग गर्नुभएको छैन" + "दुवै दिशामा लैजान सकिने स्विचरको इमोजी" + "इमोजी फर्केको दिशा बदलियो" + "इमोजी भेरियन्ट सेलेक्टर" + "%1$s र %2$s" + "छाया" + "छालाको फिक्का रङ" + "छालाको मध्यम फिक्का रङ" + "छालाको मध्यम रङ" + "छालाको मध्यम गाढा रङ" + "छालाको गाढा रङ" + diff --git a/emojipicker/app/src/main/androidx/res/values-nl/strings.xml b/emojipicker/app/src/main/androidx/res/values-nl/strings.xml new file mode 100644 index 000000000..12d8b4054 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-nl/strings.xml @@ -0,0 +1,42 @@ + + + + + "ONLANGS GEBRUIKT" + "SMILEYS EN EMOTIES" + "MENSEN" + "DIEREN EN NATUUR" + "ETEN EN DRINKEN" + "REIZEN EN PLAATSEN" + "ACTIVITEITEN EN EVENEMENTEN" + "OBJECTEN" + "SYMBOLEN" + "VLAGGEN" + "Geen emoji\'s beschikbaar" + "Je hebt nog geen emoji\'s gebruikt" + "bidirectionele emoji-schakelaar" + "richting van emoji omgewisseld" + "emoji-variantkiezer" + "%1$s en %2$s" + "schaduw" + "lichte huidskleur" + "middellichte huidskleur" + "medium huidskleur" + "middeldonkere huidskleur" + "donkere huidskleur" + diff --git a/emojipicker/app/src/main/androidx/res/values-or/strings.xml b/emojipicker/app/src/main/androidx/res/values-or/strings.xml new file mode 100644 index 000000000..30ffd391f --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-or/strings.xml @@ -0,0 +1,42 @@ + + + + + "ବର୍ତ୍ତମାନ ବ୍ୟବହାର କରାଯାଇଛି" + "ସ୍ମାଇଲି ଓ ଆବେଗଗୁଡ଼ିକ" + "ଲୋକମାନେ" + "ଜୀବଜନ୍ତୁ ଓ ପ୍ରକୃତି" + "ଖାଦ୍ୟ ଓ ପାନୀୟ" + "ଟ୍ରାଭେଲ ଓ ସ୍ଥାନଗୁଡ଼ିକ" + "କାର୍ଯ୍ୟକଳାପ ଓ ଇଭେଣ୍ଟଗୁଡ଼ିକ" + "ଅବଜେକ୍ଟଗୁଡ଼ିକ" + "ଚିହ୍ନଗୁଡ଼ିକ" + "ଫ୍ଲାଗଗୁଡ଼ିକ" + "କୌଣସି ଇମୋଜି ଉପଲବ୍ଧ ନାହିଁ" + "ଆପଣ ଏପର୍ଯ୍ୟନ୍ତ କୌଣସି ଇମୋଜି ବ୍ୟବହାର କରିନାହାଁନ୍ତି" + "ଇମୋଜିର ବାଇଡାଇରେକ୍ସନାଲ ସୁଇଚର" + "ଇମୋଜି ଫେସିଂ ଦିଗନିର୍ଦ୍ଦେଶ ସୁଇଚ କରାଯାଇଛି" + "ଇମୋଜି ଭାରିଏଣ୍ଟ ଚୟନକାରୀ" + "%1$s ଏବଂ %2$s" + "ସେଡୋ" + "ଲାଇଟ ସ୍କିନ ଟୋନ" + "ମଧ୍ୟମ ଲାଇଟ ସ୍କିନ ଟୋନ" + "ମଧ୍ୟମ ସ୍କିନ ଟୋନ" + "ମଧ୍ୟମ ଡାର୍କ ସ୍କିନ ଟୋନ" + "ଡାର୍କ ସ୍କିନ ଟୋନ" + diff --git a/emojipicker/app/src/main/androidx/res/values-pa/strings.xml b/emojipicker/app/src/main/androidx/res/values-pa/strings.xml new file mode 100644 index 000000000..85db6c7f4 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-pa/strings.xml @@ -0,0 +1,42 @@ + + + + + "ਹਾਲ ਹੀ ਵਿੱਚ ਵਰਤਿਆ ਗਿਆ" + "ਸਮਾਈਲੀ ਅਤੇ ਜਜ਼ਬਾਤ" + "ਲੋਕ" + "ਜਾਨਵਰ ਅਤੇ ਕੁਦਰਤ" + "ਖਾਣਾ ਅਤੇ ਪੀਣਾ" + "ਯਾਤਰਾ ਅਤੇ ਥਾਵਾਂ" + "ਸਰਗਰਮੀਆਂ ਅਤੇ ਇਵੈਂਟ" + "ਵਸਤੂਆਂ" + "ਚਿੰਨ੍ਹ" + "ਝੰਡੇ" + "ਕੋਈ ਇਮੋਜੀ ਉਪਲਬਧ ਨਹੀਂ ਹੈ" + "ਤੁਸੀਂ ਹਾਲੇ ਤੱਕ ਕਿਸੇ ਵੀ ਇਮੋਜੀ ਦੀ ਵਰਤੋਂ ਨਹੀਂ ਕੀਤੀ ਹੈ" + "ਇਮੋਜੀ ਬਾਇਡਾਇਰੈਕਸ਼ਨਲ ਸਵਿੱਚਰ" + "ਇਮੋਜੀ ਦੀ ਦਿਸ਼ਾ ਬਦਲ ਦਿੱਤੀ ਗਈ" + "ਇਮੋਜੀ ਕਿਸਮ ਚੋਣਕਾਰ" + "%1$s ਅਤੇ %2$s" + "ਸ਼ੈਡੋ" + "ਚਮੜੀ ਦਾ ਹਲਕਾ ਰੰਗ" + "ਚਮੜੀ ਦਾ ਦਰਮਿਆਨਾ ਹਲਕਾ ਰੰਗ" + "ਚਮੜੀ ਦਾ ਦਰਮਿਆਨਾ ਰੰਗ" + "ਚਮੜੀ ਦਾ ਦਰਮਿਆਨਾ ਗੂੜ੍ਹਾ ਰੰਗ" + "ਚਮੜੀ ਦਾ ਗੂੜ੍ਹਾ ਰੰਗ" + diff --git a/emojipicker/app/src/main/androidx/res/values-pl/strings.xml b/emojipicker/app/src/main/androidx/res/values-pl/strings.xml new file mode 100644 index 000000000..3ed8bd349 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-pl/strings.xml @@ -0,0 +1,42 @@ + + + + + "OSTATNIO UŻYWANE" + "EMOTIKONY" + "UCZESTNICY" + "ZWIERZĘTA I PRZYRODA" + "JEDZENIE I NAPOJE" + "PODRÓŻE I MIEJSCA" + "DZIAŁANIA I ZDARZENIA" + "PRZEDMIOTY" + "SYMBOLE" + "FLAGI" + "Brak dostępnych emotikonów" + "Żadne emotikony nie zostały jeszcze użyte" + "dwukierunkowy przełącznik emotikonów" + "zmieniono kierunek emotikonów" + "selektor wariantu emotikona" + "%1$s i %2$s" + "cień" + "jasny odcień skóry" + "średnio jasny odcień skóry" + "pośredni odcień skóry" + "średnio ciemny odcień skóry" + "ciemny odcień skóry" + diff --git a/emojipicker/app/src/main/androidx/res/values-pt-rBR/strings.xml b/emojipicker/app/src/main/androidx/res/values-pt-rBR/strings.xml new file mode 100644 index 000000000..5883fcb3c --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-pt-rBR/strings.xml @@ -0,0 +1,42 @@ + + + + + "USADOS RECENTEMENTE" + "CARINHAS E EMOTICONS" + "PESSOAS" + "ANIMAIS E NATUREZA" + "COMIDAS E BEBIDAS" + "VIAGENS E LUGARES" + "ATIVIDADES E EVENTOS" + "OBJETOS" + "SÍMBOLOS" + "BANDEIRAS" + "Não há emojis disponíveis" + "Você ainda não usou emojis" + "seletor bidirecional de emojis" + "emoji virado para a direção trocada" + "seletor de variante do emoji" + "%1$s e %2$s" + "sombra" + "tom de pele claro" + "tom de pele médio-claro" + "tom de pele médio" + "tom de pele médio-escuro" + "tom de pele escuro" + diff --git a/emojipicker/app/src/main/androidx/res/values-pt-rPT/strings.xml b/emojipicker/app/src/main/androidx/res/values-pt-rPT/strings.xml new file mode 100644 index 000000000..2ef06acc4 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-pt-rPT/strings.xml @@ -0,0 +1,42 @@ + + + + + "USADOS RECENTEMENTE" + "EMOTICONS E ÍCONES EXPRESSIVOS" + "PESSOAS" + "ANIMAIS E NATUREZA" + "ALIMENTOS E BEBIDAS" + "VIAGENS E LOCAIS" + "ATIVIDADES E EVENTOS" + "OBJETOS" + "SÍMBOLOS" + "BANDEIRAS" + "Nenhum emoji disponível" + "Ainda não utilizou emojis" + "comutador bidirecional de emojis" + "direção voltada para o emoji alterada" + "seletor de variantes de emojis" + "%1$s e %2$s" + "sombra" + "tom de pele claro" + "tom de pele claro médio" + "tom de pele médio" + "tom de pele escuro médio" + "tom de pele escuro" + diff --git a/emojipicker/app/src/main/androidx/res/values-pt/strings.xml b/emojipicker/app/src/main/androidx/res/values-pt/strings.xml new file mode 100644 index 000000000..5883fcb3c --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-pt/strings.xml @@ -0,0 +1,42 @@ + + + + + "USADOS RECENTEMENTE" + "CARINHAS E EMOTICONS" + "PESSOAS" + "ANIMAIS E NATUREZA" + "COMIDAS E BEBIDAS" + "VIAGENS E LUGARES" + "ATIVIDADES E EVENTOS" + "OBJETOS" + "SÍMBOLOS" + "BANDEIRAS" + "Não há emojis disponíveis" + "Você ainda não usou emojis" + "seletor bidirecional de emojis" + "emoji virado para a direção trocada" + "seletor de variante do emoji" + "%1$s e %2$s" + "sombra" + "tom de pele claro" + "tom de pele médio-claro" + "tom de pele médio" + "tom de pele médio-escuro" + "tom de pele escuro" + diff --git a/emojipicker/app/src/main/androidx/res/values-ro/strings.xml b/emojipicker/app/src/main/androidx/res/values-ro/strings.xml new file mode 100644 index 000000000..45fad5a7e --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-ro/strings.xml @@ -0,0 +1,42 @@ + + + + + "FOLOSITE RECENT" + "EMOTICOANE ȘI EMOȚII" + "PERSOANE" + "ANIMALE ȘI NATURĂ" + "MÂNCARE ȘI BĂUTURĂ" + "CĂLĂTORII ȘI LOCAȚII" + "ACTIVITĂȚI ȘI EVENIMENTE" + "OBIECTE" + "SIMBOLURI" + "STEAGURI" + "Nu sunt disponibile emoji-uri" + "Încă nu ai folosit emoji" + "comutator bidirecțional de emojiuri" + "direcția de orientare a emojiului comutată" + "selector de variante de emoji" + "%1$s și %2$s" + "umbră" + "nuanță deschisă a pielii" + "nuanță deschisă medie a pielii" + "nuanță medie a pielii" + "nuanță închisă medie a pielii" + "nuanță închisă a pielii" + diff --git a/emojipicker/app/src/main/androidx/res/values-ru/strings.xml b/emojipicker/app/src/main/androidx/res/values-ru/strings.xml new file mode 100644 index 000000000..ecf42faa4 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-ru/strings.xml @@ -0,0 +1,42 @@ + + + + + "НЕДАВНИЕ" + "СМАЙЛИКИ И ЭМОЦИИ" + "ЛЮДИ" + "ПРИРОДА И ЖИВОТНЫЕ" + "ЕДА И НАПИТКИ" + "ПУТЕШЕСТВИЯ" + "ДЕЙСТВИЯ И СОБЫТИЯ" + "ОБЪЕКТЫ" + "СИМВОЛЫ" + "ФЛАГИ" + "Нет доступных эмодзи" + "Вы ещё не использовали эмодзи" + "Двухсторонний переключатель эмодзи" + "изменен поворот лица эмодзи" + "выбор вариантов эмодзи" + "%1$s и %2$s" + "теневой" + "светлый оттенок кожи" + "умеренно светлый оттенок кожи" + "нейтральный оттенок кожи" + "умеренно темный оттенок кожи" + "темный оттенок кожи" + diff --git a/emojipicker/app/src/main/androidx/res/values-si/strings.xml b/emojipicker/app/src/main/androidx/res/values-si/strings.xml new file mode 100644 index 000000000..2ecdc77b3 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-si/strings.xml @@ -0,0 +1,42 @@ + + + + + "මෑතදී භාවිත කළ" + "සිනාසීම් සහ චිත්තවේග" + "පුද්ගලයින්" + "සතුන් හා ස්වභාවධර්මය" + "ආහාර පාන" + "සංචාර හා ස්ථාන" + "ක්‍රියාකාරකම් සහ සිදුවීම්" + "වස්තු" + "සංකේත" + "ධජ" + "ඉමොජි කිසිවක් නොලැබේ" + "ඔබ තවමත් කිසිදු ඉමෝජියක් භාවිතා කර නැත" + "ද්විත්ව දිශා ඉමොජි මාරුකරණය" + "ඉමොජි මුහුණ දෙන දිශාව මාරු විය" + "ඉමොජි ප්‍රභේද තෝරකය" + "%1$s සහ %2$s" + "සෙවනැල්ල" + "ලා සමේ වර්ණය" + "මධ්‍යම ලා සම් වර්ණය" + "මධ්‍යම සම් වර්ණය" + "මධ්‍යම අඳුරු සම් වර්ණය" + "අඳුරු සම් වර්ණය" + diff --git a/emojipicker/app/src/main/androidx/res/values-sk/strings.xml b/emojipicker/app/src/main/androidx/res/values-sk/strings.xml new file mode 100644 index 000000000..11ed0eeaa --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-sk/strings.xml @@ -0,0 +1,42 @@ + + + + + "NEDÁVNO POUŽITÉ" + "SMAJLÍKY A EMÓCIE" + "ĽUDIA" + "ZVIERATÁ A PRÍRODA" + "JEDLO A NÁPOJE" + "CESTOVANIE A MIESTA" + "AKTIVITY A UDALOSTI" + "PREDMETY" + "SYMBOLY" + "VLAJKY" + "Nie sú k dispozícii žiadne emodži" + "Zatiaľ ste nepoužili žiadne emodži" + "obojsmerný prepínač emodži" + "smer otočenia emodži bol prepnutý" + "selektor variantu emodži" + "%1$s a %2$s" + "tieň" + "svetlý odtieň pokožky" + "stredne svetlý odtieň pokožky" + "stredný odtieň pokožky" + "stredne tmavý odtieň pokožky" + "tmavý odtieň pokožky" + diff --git a/emojipicker/app/src/main/androidx/res/values-sl/strings.xml b/emojipicker/app/src/main/androidx/res/values-sl/strings.xml new file mode 100644 index 000000000..f345226d0 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-sl/strings.xml @@ -0,0 +1,42 @@ + + + + + "NEDAVNO UPORABLJENI" + "ČUSTVENI SIMBOLI IN ČUSTVA" + "OSEBE" + "ŽIVALI IN NARAVA" + "HRANA IN PIJAČA" + "POTOVANJE IN MESTA" + "DEJAVNOSTI IN DOGODKI" + "PREDMETI" + "SIMBOLI" + "ZASTAVE" + "Ni emodžijev" + "Uporabili niste še nobenega emodžija." + "dvosmerni preklopnik emodžijev" + "preklopljena usmerjenost emodžija" + "Izbirnik različice emodžija" + "%1$s in %2$s" + "senčenje" + "svetel odtenek kože" + "srednje svetel odtenek kože" + "srednji odtenek kože" + "srednje temen odtenek kože" + "temen odtenek kože" + diff --git a/emojipicker/app/src/main/androidx/res/values-sq/strings.xml b/emojipicker/app/src/main/androidx/res/values-sq/strings.xml new file mode 100644 index 000000000..f30f751ef --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-sq/strings.xml @@ -0,0 +1,42 @@ + + + + + "PËRDORUR SË FUNDI" + "BUZËQESHJE DHE EMOCIONE" + "NJERËZ" + "KAFSHË DHE NATYRË" + "USHQIME DHE PIJE" + "UDHËTIME DHE VENDE" + "AKTIVITETE DHE NGJARJE" + "OBJEKTE" + "SIMBOLE" + "FLAMUJ" + "Nuk ofrohen emoji" + "Nuk ke përdorur ende asnjë emoji" + "ndërruesi me dy drejtime për emoji-t" + "drejtimi i emoji-t u ndryshua" + "përzgjedhësi i variantit të emoji-t" + "%1$s dhe %2$s" + "hije" + "ton lëkure i zbehtë" + "ton lëkure mesatarisht i zbehtë" + "ton lëkure mesatar" + "ton lëkure mesatarisht i errët" + "ton lëkure i errët" + diff --git a/emojipicker/app/src/main/androidx/res/values-sr/strings.xml b/emojipicker/app/src/main/androidx/res/values-sr/strings.xml new file mode 100644 index 000000000..67d3619f0 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-sr/strings.xml @@ -0,0 +1,42 @@ + + + + + "НЕДАВНО КОРИШЋЕНО" + "СМАЈЛИЈИ И ЕМОЦИЈЕ" + "ЉУДИ" + "ЖИВОТИЊЕ И ПРИРОДА" + "ХРАНА И ПИЋЕ" + "ПУТОВАЊА И МЕСТА" + "АКТИВНОСТИ И ДОГАЂАЈИ" + "ОБЈЕКТИ" + "СИМБОЛИ" + "ЗАСТАВЕ" + "Емоџији нису доступни" + "Још нисте користили емоџије" + "двосмерни пребацивач емоџија" + "смер емоџија је промењен" + "бирач варијанти емоџија" + "%1$s и %2$s" + "сенка" + "кожа светле пути" + "кожа средњесветле пути" + "кожа средње пути" + "кожа средњетамне пути" + "кожа тамне пути" + diff --git a/emojipicker/app/src/main/androidx/res/values-sv/strings.xml b/emojipicker/app/src/main/androidx/res/values-sv/strings.xml new file mode 100644 index 000000000..dede0672c --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-sv/strings.xml @@ -0,0 +1,42 @@ + + + + + "NYLIGEN ANVÄNDA" + "KÄNSLOIKONER OCH KÄNSLOR" + "PERSONER" + "DJUR OCH NATUR" + "MAT OCH DRYCK" + "RESOR OCH PLATSER" + "AKTIVITETER OCH HÄNDELSER" + "FÖREMÅL" + "SYMBOLER" + "FLAGGOR" + "Inga emojier tillgängliga" + "Du har ännu inte använt emojis" + "dubbelriktad emojiväxlare" + "emojins riktning har bytts" + "Väljare av emoji-varianter" + "%1$s och %2$s" + "skugga" + "ljus hudfärg" + "medelljus hudfärg" + "medelmörk hudfärg" + "mellanmörk hudfärg" + "mörk hudfärg" + diff --git a/emojipicker/app/src/main/androidx/res/values-sw/strings.xml b/emojipicker/app/src/main/androidx/res/values-sw/strings.xml new file mode 100644 index 000000000..3f7e24b06 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-sw/strings.xml @@ -0,0 +1,42 @@ + + + + + "ZILIZOTUMIKA HIVI MAJUZI" + "VICHESHI NA HISIA" + "WATU" + "WANYAMA NA MAZINGIRA" + "VYAKULA NA VINYWAJI" + "SAFARI NA MAENEO" + "SHUGHULI NA MATUKIO" + "VITU" + "ALAMA" + "BENDERA" + "Hakuna emoji zinazopatikana" + "Bado hujatumia emoji zozote" + "kibadilishaji cha emoji cha pande mbili" + "imebadilisha upande ambao emoji inaangalia" + "kiteuzi cha kibadala cha emoji" + "%1$s na %2$s" + "kivuli" + "ngozi ya rangi nyeupe" + "ngozi ya rangi nyeupe kiasi" + "ngozi ya rangi ya maji ya kunde" + "ngozi ya rangi nyeusi kiasi" + "ngozi ya rangi nyeusi" + diff --git a/emojipicker/app/src/main/androidx/res/values-ta/strings.xml b/emojipicker/app/src/main/androidx/res/values-ta/strings.xml new file mode 100644 index 000000000..5954c77f6 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-ta/strings.xml @@ -0,0 +1,42 @@ + + + + + "சமீபத்தில் பயன்படுத்தியவை" + "ஸ்மைலிகளும் எமோடிகான்களும்" + "நபர்" + "விலங்குகளும் இயற்கையும்" + "உணவும் பானமும்" + "பயணமும் இடங்களும்" + "செயல்பாடுகளும் நிகழ்வுகளும்" + "பொருட்கள்" + "சின்னங்கள்" + "கொடிகள்" + "ஈமோஜிகள் எதுவுமில்லை" + "இதுவரை ஈமோஜி எதையும் நீங்கள் பயன்படுத்தவில்லை" + "ஈமோஜி இருபக்க மாற்றி" + "ஈமோஜி காட்டப்படும் திசை மாற்றப்பட்டது" + "ஈமோஜி வகைத் தேர்வி" + "%1$s மற்றும் %2$s" + "நிழல்" + "வெள்ளை நிறம்" + "கொஞ்சம் வெள்ளை நிறம்" + "மாநிறம்" + "கொஞ்சம் கருநிறம்" + "கருநிறம்" + diff --git a/emojipicker/app/src/main/androidx/res/values-te/strings.xml b/emojipicker/app/src/main/androidx/res/values-te/strings.xml new file mode 100644 index 000000000..db21e73a6 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-te/strings.xml @@ -0,0 +1,42 @@ + + + + + "ఇటీవల ఉపయోగించినవి" + "స్మైలీలు, ఎమోషన్‌లు" + "వ్యక్తులు" + "జంతువులు, ప్రకృతి" + "ఆహారం, పానీయం" + "ప్రయాణం, స్థలాలు" + "యాక్టివిటీలు, ఈవెంట్‌లు" + "ఆబ్జెక్ట్‌లు" + "గుర్తులు" + "ఫ్లాగ్‌లు" + "ఎమోజీలు ఏవీ అందుబాటులో లేవు" + "మీరు ఇంకా ఎమోజీలు ఏవీ ఉపయోగించలేదు" + "ఎమోజీ ద్విదిశాత్మక స్విచ్చర్" + "ఎమోజీ దిశ మార్చబడింది" + "ఎమోజి రకాన్ని ఎంపిక చేసే సాధనం" + "%1$s, %2$s" + "షాడో" + "లైట్ స్కిన్ రంగు" + "చామనఛాయ లైట్ స్కిన్ రంగు" + "చామనఛాయ స్కిన్ రంగు" + "చామనఛాయ డార్క్ స్కిన్ రంగు" + "డార్క్ స్కిన్ రంగు" + diff --git a/emojipicker/app/src/main/androidx/res/values-th/strings.xml b/emojipicker/app/src/main/androidx/res/values-th/strings.xml new file mode 100644 index 000000000..74d28694e --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-th/strings.xml @@ -0,0 +1,42 @@ + + + + + "ใช้ล่าสุด" + "หน้ายิ้มและอารมณ์" + "ผู้คน" + "สัตว์และธรรมชาติ" + "อาหารและเครื่องดื่ม" + "การเดินทางและสถานที่" + "กิจกรรมและเหตุการณ์" + "วัตถุ" + "สัญลักษณ์" + "ธง" + "ไม่มีอีโมจิ" + "คุณยังไม่ได้ใช้อีโมจิเลย" + "ตัวสลับอีโมจิแบบ 2 ทาง" + "เปลี่ยนทิศทางการหันหน้าของอีโมจิแล้ว" + "ตัวเลือกตัวแปรอีโมจิ" + "%1$s และ %2$s" + "เงา" + "โทนผิวสีอ่อน" + "โทนผิวสีอ่อนปานกลาง" + "โทนผิวสีปานกลาง" + "โทนผิวสีเข้มปานกลาง" + "โทนผิวสีเข้ม" + diff --git a/emojipicker/app/src/main/androidx/res/values-tl/strings.xml b/emojipicker/app/src/main/androidx/res/values-tl/strings.xml new file mode 100644 index 000000000..2a14fba77 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-tl/strings.xml @@ -0,0 +1,42 @@ + + + + + "KAMAKAILANG GINAMIT" + "MGA SMILEY AT MGA EMOSYON" + "MGA TAO" + "MGA HAYOP AT KALIKASAN" + "PAGKAIN AT INUMIN" + "PAGLALAKBAY AT MGA LUGAR" + "MGA AKTIBIDAD AT EVENT" + "MGA BAGAY" + "MGA SIMBOLO" + "MGA BANDILA" + "Walang available na emoji" + "Hindi ka pa gumamit ng anumang emoji" + "bidirectional na switcher ng emoji" + "pinalitan ang direksyon kung saan nakaharap ang emoji" + "selector ng variant ng emoji" + "%1$s at %2$s" + "shadow" + "maputing kulay ng balat" + "katamtamang maputing kulay ng balat" + "katamtamang kulay ng balat" + "katamtamang maitim na kulay ng balat" + "maitim na kulay ng balat" + diff --git a/emojipicker/app/src/main/androidx/res/values-tr/strings.xml b/emojipicker/app/src/main/androidx/res/values-tr/strings.xml new file mode 100644 index 000000000..f0d13cddf --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-tr/strings.xml @@ -0,0 +1,42 @@ + + + + + "SON KULLANILANLAR" + "SMILEY\'LER VE İFADELER" + "İNSANLAR" + "HAYVANLAR VE DOĞA" + "YİYECEK VE İÇECEK" + "SEYAHAT VE YERLER" + "AKTİVİTELER VE ETKİNLİKLER" + "NESNELER" + "SEMBOLLER" + "BAYRAKLAR" + "Kullanılabilir emoji yok" + "Henüz emoji kullanmadınız" + "çift yönlü emoji değiştirici" + "emoji yönü değiştirildi" + "emoji varyant seçici" + "%1$s ve %2$s" + "gölge" + "açık ten rengi" + "orta-açık ten rengi" + "orta ten rengi" + "orta-koyu ten rengi" + "koyu ten rengi" + diff --git a/emojipicker/app/src/main/androidx/res/values-uk/strings.xml b/emojipicker/app/src/main/androidx/res/values-uk/strings.xml new file mode 100644 index 000000000..46e9e3dcd --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-uk/strings.xml @@ -0,0 +1,42 @@ + + + + + "НЕЩОДАВНО ВИКОРИСТАНІ" + "СМАЙЛИКИ Й ЕМОЦІЇ" + "ЛЮДИ" + "ТВАРИНИ Й ПРИРОДА" + "ЇЖА Й НАПОЇ" + "ПОДОРОЖІ Й МІСЦЯ" + "АКТИВНІСТЬ І ПОДІЇ" + "ОБ’ЄКТИ" + "СИМВОЛИ" + "ПРАПОРИ" + "Немає смайлів" + "Ви ще не використовували смайли" + "двосторонній перемикач смайлів" + "змінено напрям обличчя смайлів" + "засіб вибору варіанта смайла" + "%1$s і %2$s" + "тінь" + "світлий відтінок шкіри" + "помірно світлий відтінок шкіри" + "помірний відтінок шкіри" + "помірно темний відтінок шкіри" + "темний відтінок шкіри" + diff --git a/emojipicker/app/src/main/androidx/res/values-ur/strings.xml b/emojipicker/app/src/main/androidx/res/values-ur/strings.xml new file mode 100644 index 000000000..68fa937dd --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-ur/strings.xml @@ -0,0 +1,42 @@ + + + + + "حال ہی میں استعمال کردہ" + "اسمائلیز اور جذبات" + "لوگ" + "جانور اور قدرت" + "خوراک اور مشروب" + "سفر اور جگہیں" + "سرگرمیاں اور ایونٹس" + "آبجیکٹس" + "علامات" + "جھنڈے" + "کوئی بھی ایموجی دستیاب نہیں ہے" + "آپ نے ابھی تک کوئی بھی ایموجی استعمال نہیں کی ہے" + "دو طرفہ سوئچر ایموجی" + "ایموجی کا سمتِ رخ سوئچ کر دیا گیا" + "ایموجی کی قسم کا منتخب کنندہ" + "‏‎%1$s اور ‎%2$s" + "پرچھائیں" + "جلد کا ہلکا ٹون" + "جلد کا متوسط ہلکا ٹون" + "جلد کا متوسط ٹون" + "جلد کا متوسط گہرا ٹون" + "جلد کا گہرا ٹون" + diff --git a/emojipicker/app/src/main/androidx/res/values-uz/strings.xml b/emojipicker/app/src/main/androidx/res/values-uz/strings.xml new file mode 100644 index 000000000..6610ffd50 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-uz/strings.xml @@ -0,0 +1,42 @@ + + + + + "YAQINDA ISHLATILGAN" + "KULGICH VA EMOJILAR" + "ODAMLAR" + "HAYVONLAR VA TABIAT" + "TAOM VA ICHIMLIKLAR" + "SAYOHAT VA JOYLAR" + "HODISA VA TADBIRLAR" + "BUYUMLAR" + "BELGILAR" + "BAYROQCHALAR" + "Hech qanday emoji mavjud emas" + "Hanuz birorta emoji ishlatmagansiz" + "ikki tomonlama emoji almashtirgich" + "emoji yuzlanish tomoni almashdi" + "emoji variant tanlagich" + "%1$s va %2$s" + "soya" + "och rang tusli" + "oʻrtacha och rang tusli" + "neytral rang tusli" + "oʻrtacha toʻq rang tusli" + "toʻq rang tusli" + diff --git a/emojipicker/app/src/main/androidx/res/values-vi/strings.xml b/emojipicker/app/src/main/androidx/res/values-vi/strings.xml new file mode 100644 index 000000000..9e1eac8ec --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-vi/strings.xml @@ -0,0 +1,42 @@ + + + + + "MỚI DÙNG GẦN ĐÂY" + "MẶT CƯỜI VÀ BIỂU TƯỢNG CẢM XÚC" + "MỌI NGƯỜI" + "ĐỘNG VẬT VÀ THIÊN NHIÊN" + "THỰC PHẨM VÀ ĐỒ UỐNG" + "DU LỊCH VÀ ĐỊA ĐIỂM" + "HOẠT ĐỘNG VÀ SỰ KIỆN" + "ĐỒ VẬT" + "BIỂU TƯỢNG" + "CỜ" + "Không có biểu tượng cảm xúc nào" + "Bạn chưa sử dụng biểu tượng cảm xúc nào" + "trình chuyển đổi hai chiều biểu tượng cảm xúc" + "đã chuyển hướng mặt của biểu tượng cảm xúc" + "bộ chọn biến thể biểu tượng cảm xúc" + "%1$s và %2$s" + "bóng" + "tông màu da sáng" + "tông màu da sáng trung bình" + "tông màu da trung bình" + "tông màu da tối trung bình" + "tông màu da tối" + diff --git a/emojipicker/app/src/main/androidx/res/values-zh-rCN/strings.xml b/emojipicker/app/src/main/androidx/res/values-zh-rCN/strings.xml new file mode 100644 index 000000000..453eb005a --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-zh-rCN/strings.xml @@ -0,0 +1,42 @@ + + + + + "最近使用过" + "表情符号" + "人物" + "动物和自然" + "食品和饮料" + "旅游和地点" + "活动和庆典" + "物体" + "符号" + "旗帜" + "没有可用的表情符号" + "您尚未使用过任何表情符号" + "表情符号双向切换器" + "已切换表情符号朝向" + "表情符号变体选择器" + "%1$s和%2$s" + "阴影" + "浅肤色" + "中等偏浅肤色" + "中等肤色" + "中等偏深肤色" + "深肤色" + diff --git a/emojipicker/app/src/main/androidx/res/values-zh-rHK/strings.xml b/emojipicker/app/src/main/androidx/res/values-zh-rHK/strings.xml new file mode 100644 index 000000000..21b7318ff --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-zh-rHK/strings.xml @@ -0,0 +1,42 @@ + + + + + "最近使用過" + "表情符號" + "人物" + "動物和大自然" + "飲食" + "旅遊和地點" + "活動和事件" + "物件" + "符號" + "旗幟" + "沒有可用的 Emoji" + "你尚未使用任何 Emoji" + "Emoji 雙向切換工具" + "轉咗 Emoji 方向" + "Emoji 變化版本選取器" + "%1$s和%2$s" + "陰影" + "淺膚色" + "偏淺膚色" + "中等膚色" + "偏深膚色" + "深膚色" + diff --git a/emojipicker/app/src/main/androidx/res/values-zh-rTW/strings.xml b/emojipicker/app/src/main/androidx/res/values-zh-rTW/strings.xml new file mode 100644 index 000000000..546e9de25 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-zh-rTW/strings.xml @@ -0,0 +1,42 @@ + + + + + "最近使用過" + "表情符號" + "人物" + "動物與大自然" + "飲食" + "旅行與地點" + "活動與事件" + "物品" + "符號" + "旗幟" + "沒有可用的表情符號" + "你尚未使用任何表情符號" + "表情符號雙向切換器" + "已切換表情符號方向" + "表情符號變化版本選取器" + "%1$s和%2$s" + "陰影" + "淺膚色" + "偏淺膚色" + "中等膚色" + "偏深膚色" + "深膚色" + diff --git a/emojipicker/app/src/main/androidx/res/values-zu/strings.xml b/emojipicker/app/src/main/androidx/res/values-zu/strings.xml new file mode 100644 index 000000000..3918f298b --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values-zu/strings.xml @@ -0,0 +1,42 @@ + + + + + "EZISANDA KUSETSHENZISWA" + "AMASMAYILI NEMIZWA" + "ABANTU" + "IZILWANE NENDALO" + "UKUDLA NESIPHUZO" + "UKUVAKASHA NEZINDAWO" + "IMISEBENZI NEMICIMBI" + "IZINTO" + "AMASIMBULI" + "AMAFULEGI" + "Awekho ama-emoji atholakalayo" + "Awukasebenzisi noma yimaphi ama-emoji okwamanje" + "isishintshi se-emoji ye-bidirectional" + "isikhombisi-ndlela esibheke ku-emoji sishintshiwe" + "isikhethi esihlukile se-emoji" + "Okuthi %1$s nokuthi %2$s" + "isithunzi" + "ibala lesikhumba elikhanyayo" + "ibala lesikhumba elikhanya ngokumaphakathi" + "ibala lesikhumba eliphakathi nendawo" + "ibala lesikhumba elinsundu ngokumaphakathi" + "ibala lesikhumba elimnyama" + diff --git a/emojipicker/app/src/main/androidx/res/values/arrays.xml b/emojipicker/app/src/main/androidx/res/values/arrays.xml new file mode 100644 index 000000000..59961b629 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values/arrays.xml @@ -0,0 +1,68 @@ + + + + + + @raw/emoji_category_emotions + @raw/emoji_category_people + @raw/emoji_category_animals_nature + @raw/emoji_category_food_drink + @raw/emoji_category_travel_places + @raw/emoji_category_activity + @raw/emoji_category_objects + @raw/emoji_category_symbols + @raw/emoji_category_flags + + + + + @raw/emoji_category_emotions + + @raw/emoji_category_animals_nature + @raw/emoji_category_food_drink + @raw/emoji_category_travel_places + @raw/emoji_category_activity + @raw/emoji_category_objects + @raw/emoji_category_symbols + @raw/emoji_category_flags + + + + @drawable/gm_filled_emoji_emotions_vd_theme_24 + @drawable/gm_filled_emoji_people_vd_theme_24 + @drawable/gm_filled_emoji_nature_vd_theme_24 + @drawable/gm_filled_emoji_food_beverage_vd_theme_24 + @drawable/gm_filled_emoji_transportation_vd_theme_24 + @drawable/gm_filled_emoji_events_vd_theme_24 + @drawable/gm_filled_emoji_objects_vd_theme_24 + @drawable/gm_filled_emoji_symbols_vd_theme_24 + @drawable/gm_filled_flag_vd_theme_24 + + + + @string/emoji_category_emotions + @string/emoji_category_people + @string/emoji_category_animals_nature + @string/emoji_category_food_drink + @string/emoji_category_travel_places + @string/emoji_category_activity + @string/emoji_category_objects + @string/emoji_category_symbols + @string/emoji_category_flags + + \ No newline at end of file diff --git a/emojipicker/app/src/main/androidx/res/values/attrs.xml b/emojipicker/app/src/main/androidx/res/values/attrs.xml new file mode 100644 index 000000000..c84e3d86a --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values/attrs.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/androidx/res/values/colors.xml b/emojipicker/app/src/main/androidx/res/values/colors.xml new file mode 100644 index 000000000..b21b03572 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values/colors.xml @@ -0,0 +1,26 @@ + + + + + #edbd82 + #ba8f63 + #91674d + #875334 + #4a2f27 + + #ffffff + diff --git a/emojipicker/app/src/main/androidx/res/values/dimens.xml b/emojipicker/app/src/main/androidx/res/values/dimens.xml new file mode 100644 index 000000000..6be5c11d9 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values/dimens.xml @@ -0,0 +1,38 @@ + + + + + 39dp + 46dp + 20dp + 20dp + 28dp + 2dp + 42dp + 5dp + 5dp + 5dp + 10dp + 10dp + 10dp + 8dp + 30dp + 6dp + 24dp + 4dp + 2dp + \ No newline at end of file diff --git a/emojipicker/app/src/main/androidx/res/values/strings.xml b/emojipicker/app/src/main/androidx/res/values/strings.xml new file mode 100644 index 000000000..2e8238bcb --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values/strings.xml @@ -0,0 +1,75 @@ + + + + + RECENTLY USED + + SMILEYS AND EMOTIONS + + PEOPLE + + ANIMALS AND NATURE + + FOOD AND DRINK + + TRAVEL AND PLACES + + ACTIVITIES AND EVENTS + + OBJECTS + + SYMBOLS + + FLAGS + + + No emojis available + + You haven\'t used any emojis yet + + + emoji bidirectional switcher + + + emoji facing direction switched + + + emoji variant selector + + + %1$s and %2$s + + + shadow + + + light skin tone + + + medium light skin tone + + + medium skin tone + + + medium dark skin tone + + + dark skin tone + diff --git a/emojipicker/app/src/main/androidx/res/values/styles.xml b/emojipicker/app/src/main/androidx/res/values/styles.xml new file mode 100644 index 000000000..5a67a5346 --- /dev/null +++ b/emojipicker/app/src/main/androidx/res/values/styles.xml @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/BundledEmojiListLoader.kt b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/BundledEmojiListLoader.kt new file mode 100644 index 000000000..0a242d45f --- /dev/null +++ b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/BundledEmojiListLoader.kt @@ -0,0 +1,121 @@ + + +package com.rishabh.emojipicker + +import android.content.Context +import android.content.res.TypedArray +import androidx.annotation.DrawableRes +import androidx.core.content.res.use +import com.rishabh.emojipicker.utils.UnicodeRenderableManager +import com.rishabh.emojipicker.utils.FileCache + +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.coroutineScope + +/** + * A data loader that loads the following objects either from file based caches or from resources. + * + * categorizedEmojiData: a list that holds bundled emoji separated by category, filtered by + * renderability check. This is the data source for EmojiPickerView. + * + * emojiVariantsLookup: a map of emoji variants in bundled emoji, keyed by the base emoji. This + * allows faster variants lookup. + * + * primaryEmojiLookup: a map of base emoji to its variants in bundled emoji. This allows faster + * variants lookup. + */ +internal object BundledEmojiListLoader { + private var categorizedEmojiData: List? = null + private var emojiVariantsLookup: Map>? = null + + internal suspend fun load(context: Context) { + val categoryNames = context.resources.getStringArray(R.array.category_names) + val categoryHeaderIconIds = + context.resources.obtainTypedArray(R.array.emoji_categories_icons).use { typedArray -> + IntArray(typedArray.length()) { typedArray.getResourceId(it, 0) } + } + val resources = + if (UnicodeRenderableManager.isEmoji12Supported()) + R.array.emoji_by_category_raw_resources_gender_inclusive + else R.array.emoji_by_category_raw_resources + val emojiFileCache = FileCache.getInstance(context) + + categorizedEmojiData = + context.resources.obtainTypedArray(resources).use { ta -> + loadEmoji(ta, categoryHeaderIconIds, categoryNames, emojiFileCache, context) + } + emojiVariantsLookup = + categorizedEmojiData!! + .flatMap { it.emojiDataList } + .filter { it.variants.isNotEmpty() } + .flatMap { it.variants.map { variant -> EmojiViewItem(variant, it.variants) } } + .associate { it.emoji to it.variants } + .also { emojiVariantsLookup = it } + } + + internal fun getCategorizedEmojiData() = + categorizedEmojiData + ?: throw IllegalStateException("BundledEmojiListLoader.load is not called or complete") + + internal fun getEmojiVariantsLookup() = + emojiVariantsLookup + ?: throw IllegalStateException("BundledEmojiListLoader.load is not called or complete") + + private suspend fun loadEmoji( + ta: TypedArray, + @DrawableRes categoryHeaderIconIds: IntArray, + categoryNames: Array, + emojiFileCache: FileCache, + context: Context + ): List = coroutineScope { + (0 until ta.length()) + .map {intvalue-> + async { + emojiFileCache + .getOrPut(getCacheFileName(intvalue)) { + loadSingleCategory(context, ta.getResourceId(intvalue, 0)) + } + .let { + EmojiDataCategory(categoryHeaderIconIds[intvalue], categoryNames[intvalue], it) + } + } + } + .awaitAll() + } + + private fun loadSingleCategory( + context: Context, + resId: Int, + ): List = + context.resources + .openRawResource(resId) + .bufferedReader() + .useLines { it.toList() } + .map { filterRenderableEmojis(it.split(",")) } + .filter { it.isNotEmpty() } + .map { EmojiViewItem(it.first(), it.drop(1)) } + + private fun getCacheFileName(categoryIndex: Int) = + StringBuilder() + .append("emoji.v1.") + .append(if (EmojiPickerView.emojiCompatLoaded) 1 else 0) + .append(".") + .append(categoryIndex) + .append(".") + .append(if (UnicodeRenderableManager.isEmoji12Supported()) 1 else 0) + .toString() + + /** + * To eliminate 'Tofu' (the fallback glyph when an emoji is not renderable), check the + * renderability of emojis and keep only when they are renderable on the current device. + */ + private fun filterRenderableEmojis(emojiList: List) = + emojiList.filter { UnicodeRenderableManager.isEmojiRenderable(it) }.toList() + + internal data class EmojiDataCategory( + @DrawableRes val headerIconId: Int, + val categoryName: String, + val emojiDataList: List + ) +} diff --git a/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/DefaultRecentEmojiProvider.kt b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/DefaultRecentEmojiProvider.kt new file mode 100644 index 000000000..f525b5dd6 --- /dev/null +++ b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/DefaultRecentEmojiProvider.kt @@ -0,0 +1,40 @@ +package com.rishabh.emojipicker + +import android.content.Context +import android.content.Context.MODE_PRIVATE + +/** + * Provides recently shared emoji. This is the default recent emoji list provider. Clients could + * specify the provider by their own. + */ +internal class DefaultRecentEmojiProvider(context: Context) : RecentEmojiProvider { + + companion object { + private const val PREF_KEY_RECENT_EMOJI = "pref_key_recent_emoji" + private const val RECENT_EMOJI_LIST_FILE_NAME = "androidx.emoji2.emojipicker.preferences" + private const val SPLIT_CHAR = "," + } + + private val sharedPreferences = + context.getSharedPreferences(RECENT_EMOJI_LIST_FILE_NAME, MODE_PRIVATE) + private val recentEmojiList: MutableList = + sharedPreferences.getString(PREF_KEY_RECENT_EMOJI, null)?.split(SPLIT_CHAR)?.toMutableList() + ?: mutableListOf() + + override suspend fun getRecentEmojiList(): List { + return recentEmojiList + } + + override fun recordSelection(emoji: String) { + recentEmojiList.remove(emoji) + recentEmojiList.add(0, emoji) + saveToPreferences() + } + + private fun saveToPreferences() { + sharedPreferences + .edit() + .putString(PREF_KEY_RECENT_EMOJI, recentEmojiList.joinToString(SPLIT_CHAR)) + .commit() + } +} diff --git a/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerBodyAdapter.kt b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerBodyAdapter.kt new file mode 100644 index 000000000..1ddf443de --- /dev/null +++ b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerBodyAdapter.kt @@ -0,0 +1,126 @@ + + +package com.rishabh.emojipicker + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.ViewGroup.LayoutParams +import android.widget.TextView +import androidx.annotation.LayoutRes +import androidx.annotation.UiThread +import androidx.core.view.ViewCompat + +import androidx.recyclerview.widget.RecyclerView.Adapter +import androidx.recyclerview.widget.RecyclerView.ViewHolder +import com.rishabh.emojipicker.Extensions.toItemType + +/** RecyclerView adapter for emoji body. */ +internal class EmojiPickerBodyAdapter( + private val context: Context, + private val emojiGridColumns: Int, + private val emojiGridRows: Float?, + private val stickyVariantProvider: StickyVariantProvider, + private val emojiPickerItemsProvider: () -> EmojiPickerItems, + private val onEmojiPickedListener: EmojiPickerBodyAdapter.(EmojiViewItem) -> Unit, +) : Adapter() { + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + private var emojiCellWidth: Int? = null + private var emojiCellHeight: Int? = null + + @UiThread + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + emojiCellWidth = emojiCellWidth ?: (getParentWidth(parent) / emojiGridColumns) + emojiCellHeight = + emojiCellHeight + ?: emojiGridRows?.let { getEmojiCellTotalHeight(parent) / it }?.toInt() + ?: emojiCellWidth + + return when (viewType.toItemType()) { + ItemType.CATEGORY_TITLE -> createSimpleHolder(R.layout.category_text_view, parent) + ItemType.PLACEHOLDER_TEXT -> + createSimpleHolder(R.layout.empty_category_text_view, parent) { + minimumHeight = emojiCellHeight!! + } + ItemType.EMOJI -> { + EmojiViewHolder( + context, + emojiCellWidth!!, + emojiCellHeight!!, + stickyVariantProvider, + onEmojiPickedListener = { emojiViewItem -> + onEmojiPickedListener(emojiViewItem) + }, + onEmojiPickedFromPopupListener = { emoji -> + val baseEmoji = BundledEmojiListLoader.getEmojiVariantsLookup()[emoji]!![0] + emojiPickerItemsProvider().forEachIndexed { index, itemViewData -> + if ( + itemViewData is EmojiViewData && + BundledEmojiListLoader.getEmojiVariantsLookup()[ + itemViewData.emoji] + ?.get(0) == baseEmoji && + itemViewData.updateToSticky + ) { + itemViewData.emoji = emoji + notifyItemChanged(index) + } + } + } + ) + } + } + } + + override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) { + val item = emojiPickerItemsProvider().getBodyItem(position) + when (getItemViewType(position).toItemType()) { + ItemType.CATEGORY_TITLE -> + ViewCompat.requireViewById(viewHolder.itemView, R.id.category_name).text = + (item as CategoryTitle).title + ItemType.PLACEHOLDER_TEXT -> + ViewCompat.requireViewById( + viewHolder.itemView, + R.id.emoji_picker_empty_category_view + ) + .text = (item as PlaceholderText).text + ItemType.EMOJI -> { + (viewHolder as EmojiViewHolder).bindEmoji((item as EmojiViewData).emoji) + } + } + } + + override fun getItemId(position: Int): Long = + emojiPickerItemsProvider().getBodyItem(position).hashCode().toLong() + + override fun getItemCount(): Int { + return emojiPickerItemsProvider().size + } + + override fun getItemViewType(position: Int): Int { + return emojiPickerItemsProvider().getBodyItem(position).viewType + } + + private fun getParentWidth(parent: ViewGroup): Int { + return parent.measuredWidth - parent.paddingLeft - parent.paddingRight + } + + private fun getEmojiCellTotalHeight(parent: ViewGroup) = + parent.measuredHeight - + context.resources.getDimensionPixelSize(R.dimen.emoji_picker_category_name_height) * 2 - + context.resources.getDimensionPixelSize(R.dimen.emoji_picker_category_name_padding_top) + + private fun createSimpleHolder( + @LayoutRes layoutId: Int, + parent: ViewGroup, + init: (View.() -> Unit)? = null, + ) = + object : + ViewHolder( + layoutInflater.inflate(layoutId, parent, /* attachToRoot= */ false).also { + it.layoutParams = + LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT) + init?.invoke(it) + } + ) {} +} diff --git a/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerConstants.kt b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerConstants.kt new file mode 100644 index 000000000..e7e8d2a40 --- /dev/null +++ b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerConstants.kt @@ -0,0 +1,21 @@ + + +package com.rishabh.emojipicker + +/** A utility class to hold various constants used by the Emoji Picker library. */ +internal object EmojiPickerConstants { + + // The default number of body columns. + const val DEFAULT_BODY_COLUMNS = 9 + + // The default number of rows of recent items held. + const val DEFAULT_MAX_RECENT_ITEM_ROWS = 3 + + // The max pool size of the Emoji ItemType in RecyclerViewPool. + const val EMOJI_VIEW_POOL_SIZE = 100 + + const val ADD_VIEW_EXCEPTION_MESSAGE = "Adding views to the EmojiPickerView is unsupported" + + const val REMOVE_VIEW_EXCEPTION_MESSAGE = + "Removing views from the EmojiPickerView is unsupported" +} diff --git a/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerHeaderAdapter.kt b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerHeaderAdapter.kt new file mode 100644 index 000000000..a6c3dd010 --- /dev/null +++ b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerHeaderAdapter.kt @@ -0,0 +1,74 @@ + + +package com.rishabh.emojipicker + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.accessibility.AccessibilityEvent +import android.widget.ImageView +import androidx.core.view.ViewCompat +import androidx.recyclerview.widget.RecyclerView.Adapter +import androidx.recyclerview.widget.RecyclerView.ViewHolder + +/** RecyclerView adapter for emoji header. */ +internal class EmojiPickerHeaderAdapter( + context: Context, + private val emojiPickerItems: EmojiPickerItems, + private val onHeaderIconClicked: (Int) -> Unit, +) : Adapter() { + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + + var selectedGroupIndex: Int = 0 + set(value) { + if (value == field) return + notifyItemChanged(field) + notifyItemChanged(value) + field = value + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + return object : + ViewHolder( + layoutInflater.inflate( + R.layout.header_icon_holder, + parent, + /* attachToRoot = */ false + ) + ) {} + } + + override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) { + val isItemSelected = i == selectedGroupIndex + val headerIcon = + ViewCompat.requireViewById( + viewHolder.itemView, + R.id.emoji_picker_header_icon + ) + .apply { + setImageDrawable(context.getDrawable(emojiPickerItems.getHeaderIconId(i))) + isSelected = isItemSelected + contentDescription = emojiPickerItems.getHeaderIconDescription(i) + } + viewHolder.itemView.setOnClickListener { + onHeaderIconClicked(i) + selectedGroupIndex = i + } + if (isItemSelected) { + headerIcon.post { + headerIcon.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER) + } + } + + ViewCompat.requireViewById(viewHolder.itemView, R.id.emoji_picker_header_underline) + .apply { + visibility = if (isItemSelected) View.VISIBLE else View.GONE + isSelected = isItemSelected + } + } + + override fun getItemCount(): Int { + return emojiPickerItems.numGroups + } +} diff --git a/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerItems.kt b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerItems.kt new file mode 100644 index 000000000..fe9093d82 --- /dev/null +++ b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerItems.kt @@ -0,0 +1,97 @@ + + +package com.rishabh.emojipicker + +import androidx.annotation.DrawableRes +import androidx.annotation.IntRange + +/** + * A group of items in RecyclerView for emoji picker body. [titleItem] comes first. [contentItems] + * comes after [titleItem]. [emptyPlaceholderItem] will be served after [titleItem] only if + * [contentItems] is empty. [maxContentItemCount], if provided, will truncate [contentItems] to + * certain size. + * + * [categoryIconId] is the corresponding category icon in emoji picker header. + */ +internal class ItemGroup( + @DrawableRes internal val categoryIconId: Int, + internal val titleItem: CategoryTitle, + private val contentItems: List, + private val maxContentItemCount: Int? = null, + private val emptyPlaceholderItem: PlaceholderText? = null +) { + + val size: Int + get() = + 1 /* title */ + + when { + contentItems.isEmpty() -> if (emptyPlaceholderItem != null) 1 else 0 + maxContentItemCount != null && contentItems.size > maxContentItemCount -> + maxContentItemCount + else -> contentItems.size + } + + operator fun get(index: Int): ItemViewData { + if (index == 0) return titleItem + val contentIndex = index - 1 + if (contentIndex < contentItems.size) return contentItems[contentIndex] + if (contentIndex == 0 && emptyPlaceholderItem != null) return emptyPlaceholderItem + throw IndexOutOfBoundsException() + } + + fun getAll(): List = IntRange(0, size - 1).map { get(it) } +} + +/** A view of concatenated list of [ItemGroup]. */ +internal class EmojiPickerItems( + private val groups: List, +) : Iterable { + val size: Int + get() = groups.sumOf { it.size } + + init { + check(groups.isNotEmpty()) { "Initialized with empty categorized sources" } + } + + fun getBodyItem(@IntRange(from = 0) absolutePosition: Int): ItemViewData { + var localPosition = absolutePosition + for (group in groups) { + if (localPosition < group.size) return group[localPosition] + else localPosition -= group.size + } + throw IndexOutOfBoundsException() + } + + val numGroups: Int + get() = groups.size + + @DrawableRes + fun getHeaderIconId(@IntRange(from = 0) index: Int): Int = groups[index].categoryIconId + + fun getHeaderIconDescription(@IntRange(from = 0) index: Int): String = + groups[index].titleItem.title + + fun groupIndexByItemPosition(@IntRange(from = 0) absolutePosition: Int): Int { + var localPosition = absolutePosition + var index = 0 + for (group in groups) { + if (localPosition < group.size) return index + else { + localPosition -= group.size + index++ + } + } + throw IndexOutOfBoundsException() + } + + fun firstItemPositionByGroupIndex(@IntRange(from = 0) groupIndex: Int): Int = + groups.take(groupIndex).sumOf { it.size } + + fun groupRange(group: ItemGroup): kotlin.ranges.IntRange { + check(groups.contains(group)) + val index = groups.indexOf(group) + return firstItemPositionByGroupIndex(index).let { it until it + group.size } + } + + override fun iterator(): Iterator = groups.flatMap { it.getAll() }.iterator() +} diff --git a/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupBidirectionalDesign.kt b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupBidirectionalDesign.kt new file mode 100644 index 000000000..1829233f3 --- /dev/null +++ b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupBidirectionalDesign.kt @@ -0,0 +1,110 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.rishabh.emojipicker + +import android.content.Context +import android.view.Gravity +import android.view.View +import android.view.ViewGroup +import android.widget.FrameLayout +import android.widget.LinearLayout +import androidx.appcompat.widget.AppCompatImageView + +/** Emoji picker popup view with bidirectional UI design to switch emoji to face left or right. */ +internal class EmojiPickerPopupBidirectionalDesign( + override val context: Context, + override val targetEmojiView: View, + override val variants: List, + override val popupView: LinearLayout, + override val emojiViewOnClickListener: View.OnClickListener +) : EmojiPickerPopupDesign() { + private var emojiFacingLeft = true + + init { + updateTemplate() + } + + override fun addLayoutHeader() { + val row = + LinearLayout(context).apply { + orientation = LinearLayout.HORIZONTAL + gravity = Gravity.CENTER + layoutParams = + LinearLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + } + FrameLayout.inflate(context, R.layout.emoji_picker_popup_bidirectional, row) + .findViewById(R.id.emoji_picker_popup_bidirectional_icon) + .apply { + layoutParams = + LinearLayout.LayoutParams(targetEmojiView.width, targetEmojiView.height) + } + popupView.addView(row) + val imageView = + row.findViewById(R.id.emoji_picker_popup_bidirectional_icon) + imageView.setOnClickListener { + emojiFacingLeft = !emojiFacingLeft + updateTemplate() + popupView.removeViews(/* start= */ 1, getActualNumberOfRows()) + addRowsToPopupView() + imageView.announceForAccessibility( + context.getString(R.string.emoji_bidirectional_switcher_clicked_desc) + ) + } + } + + override fun getNumberOfRows(): Int { + // Adding one row for the bidirectional switcher. + return variants.size / 2 / BIDIRECTIONAL_COLUMN_COUNT + 1 + } + + override fun getNumberOfColumns(): Int { + return BIDIRECTIONAL_COLUMN_COUNT + } + + private fun getActualNumberOfRows(): Int { + // Removing one extra row of the bidirectional switcher. + return getNumberOfRows() - 1 + } + + private fun updateTemplate() { + template = + if (emojiFacingLeft) + arrayOf((variants.indices.filter { it % 12 < 6 }.map { it + 1 }).toIntArray()) + else arrayOf((variants.indices.filter { it % 12 >= 6 }.map { it + 1 }).toIntArray()) + + val row = getActualNumberOfRows() + val column = getNumberOfColumns() + val overrideTemplate = Array(row) { IntArray(column) } + var index = 0 + for (i in 0 until row) { + for (j in 0 until column) { + if (index < template[0].size) { + overrideTemplate[i][j] = template[0][index] + index++ + } + } + } + template = overrideTemplate + } + + companion object { + private const val BIDIRECTIONAL_COLUMN_COUNT = 6 + } +} diff --git a/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupDesign.kt b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupDesign.kt new file mode 100644 index 000000000..e55f53df5 --- /dev/null +++ b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupDesign.kt @@ -0,0 +1,89 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.rishabh.emojipicker + +import android.content.Context +import android.view.View +import android.view.ViewGroup +import android.view.accessibility.AccessibilityEvent +import android.widget.FrameLayout +import android.widget.LinearLayout + +/** Emoji picker popup view UI design. Each UI design needs to inherit this abstract class. */ +internal abstract class EmojiPickerPopupDesign { + abstract val context: Context + abstract val targetEmojiView: View + abstract val variants: List + abstract val popupView: LinearLayout + abstract val emojiViewOnClickListener: View.OnClickListener + lateinit var template: Array + + open fun addLayoutHeader() { + // no-ops + } + + open fun addRowsToPopupView() { + for (row in template) { + val rowLayout = + LinearLayout(context).apply { + orientation = LinearLayout.HORIZONTAL + layoutParams = + LinearLayout.LayoutParams( + FrameLayout.LayoutParams.WRAP_CONTENT, + FrameLayout.LayoutParams.WRAP_CONTENT + ) + } + for (item in row) { + val cell = + if (item == 0) { + EmojiView(context) + } else { + EmojiView(context).apply { + willDrawVariantIndicator = false + emoji = variants[item - 1] + setOnClickListener(emojiViewOnClickListener) + if (item == 1) { + // Hover on the first emoji in the popup + popupView.post { + sendAccessibilityEvent( + AccessibilityEvent.TYPE_VIEW_HOVER_ENTER + ) + } + } + } + } + .apply { + layoutParams = + ViewGroup.LayoutParams( + targetEmojiView.width, + targetEmojiView.height + ) + } + rowLayout.addView(cell) + } + popupView.addView(rowLayout) + } + } + + open fun addLayoutFooter() { + // no-ops + } + + abstract fun getNumberOfRows(): Int + + abstract fun getNumberOfColumns(): Int +} diff --git a/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupFlatDesign.kt b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupFlatDesign.kt new file mode 100644 index 000000000..4b5112568 --- /dev/null +++ b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupFlatDesign.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.rishabh.emojipicker + +import android.content.Context +import android.view.View +import android.widget.LinearLayout + +/** Emoji picker popup view with flat design to list emojis. */ +internal class EmojiPickerPopupFlatDesign( + override val context: Context, + override val targetEmojiView: View, + override val variants: List, + override val popupView: LinearLayout, + override val emojiViewOnClickListener: View.OnClickListener +) : EmojiPickerPopupDesign() { + init { + template = arrayOf(variants.indices.map { it + 1 }.toIntArray()) + var row = getNumberOfRows() + var column = getNumberOfColumns() + val overrideTemplate = Array(row) { IntArray(column) } + var index = 0 + for (i in 0 until row) { + for (j in 0 until column) { + if (index < template[0].size) { + overrideTemplate[i][j] = template[0][index] + index++ + } + } + } + template = overrideTemplate + } + + override fun getNumberOfRows(): Int { + val column = getNumberOfColumns() + return variants.size / column + if (variants.size % column == 0) 0 else 1 + } + + override fun getNumberOfColumns(): Int { + return minOf(FLAT_COLUMN_MAX_COUNT, template[0].size) + } + + companion object { + private const val FLAT_COLUMN_MAX_COUNT = 6 + } +} diff --git a/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupMultiSkintoneDesign.kt b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupMultiSkintoneDesign.kt new file mode 100644 index 000000000..2dab8179d --- /dev/null +++ b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupMultiSkintoneDesign.kt @@ -0,0 +1,401 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.rishabh.emojipicker + +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.Color +import android.graphics.drawable.Drawable +import android.util.Log +import android.view.ContextThemeWrapper +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.FrameLayout +import android.widget.ImageView +import android.widget.LinearLayout +import androidx.annotation.StringRes +import androidx.core.content.res.ResourcesCompat +import com.google.firebase.crashlytics.buildtools.reloc.com.google.common.collect.ImmutableMap +import com.google.firebase.crashlytics.buildtools.reloc.com.google.common.primitives.ImmutableIntArray + + +/** Emoji picker popup with multi-skintone selection panel. */ +internal class EmojiPickerPopupMultiSkintoneDesign( + override val context: Context, + override val targetEmojiView: View, + override val variants: List, + override val popupView: LinearLayout, + override val emojiViewOnClickListener: View.OnClickListener, + targetEmoji: String +) : EmojiPickerPopupDesign() { + + private val inflater = LayoutInflater.from(context) + private val resultRow = + LinearLayout(context).apply { + orientation = LinearLayout.HORIZONTAL + layoutParams = + LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + } + + private var selectedLeftSkintone = -1 + private var selectedRightSkintone = -1 + + init { + val triggerVariantIndex: Int = variants.indexOf(targetEmoji) + if (triggerVariantIndex > 0) { + selectedLeftSkintone = (triggerVariantIndex - 1) / getNumberOfColumns() + selectedRightSkintone = + triggerVariantIndex - selectedLeftSkintone * getNumberOfColumns() - 1 + } + } + + override fun addRowsToPopupView() { + for (row in 0 until getActualNumberOfRows()) { + val rowLayout = + LinearLayout(context).apply { + orientation = LinearLayout.HORIZONTAL + layoutParams = + LinearLayout.LayoutParams( + FrameLayout.LayoutParams.WRAP_CONTENT, + FrameLayout.LayoutParams.WRAP_CONTENT + ) + } + for (column in 0 until getNumberOfColumns()) { + inflater.inflate(R.layout.emoji_picker_popup_image_view, rowLayout) + val imageView = rowLayout.getChildAt(column) as ImageView + imageView.apply { + layoutParams = + LinearLayout.LayoutParams(targetEmojiView.width, targetEmojiView.height) + isClickable = true + contentDescription = getImageContentDescription(context, row, column) + if ( + (hasLeftSkintone() && row == 0 && selectedLeftSkintone == column) || + (hasRightSkintone() && row == 1 && selectedRightSkintone == column) + ) { + isSelected = true + isClickable = false + } + setImageDrawable(getDrawableRes(context, row, column)) + setOnClickListener { + var unSelectedView: View? = null + if (row == 0) { + if (hasLeftSkintone()) { + unSelectedView = rowLayout.getChildAt(selectedLeftSkintone) + } + selectedLeftSkintone = column + } else { + if (hasRightSkintone()) { + unSelectedView = rowLayout.getChildAt(selectedRightSkintone) + } + selectedRightSkintone = column + } + if (unSelectedView != null) { + unSelectedView.isSelected = false + unSelectedView.isClickable = true + } + isClickable = false + isSelected = true + processResultView() + } + } + } + popupView.addView(rowLayout) + } + } + + private fun processResultView() { + val childCount = resultRow.childCount + if (childCount < 1 || childCount > 2) { + Log.e(TAG, "processResultEmojiForRectangleLayout(): unexpected emoji result row size") + return + } + // Remove the result emoji if it's already available. It will be available after the row is + // inflated the first time. + if (childCount == 2) { + resultRow.removeViewAt(1) + } + if (hasLeftSkintone() && hasRightSkintone()) { + inflater.inflate(R.layout.emoji_picker_popup_emoji_view, resultRow) + val layout = resultRow.getChildAt(1) as LinearLayout + layout.findViewById(R.id.emoji_picker_popup_emoji_view).apply { + willDrawVariantIndicator = false + isClickable = true + emoji = + variants[ + selectedLeftSkintone * getNumberOfColumns() + selectedRightSkintone + 1] + setOnClickListener(emojiViewOnClickListener) + layoutParams = + LinearLayout.LayoutParams(targetEmojiView.width, targetEmojiView.height) + } + layout.findViewById(R.id.emoji_picker_popup_emoji_view_wrapper).apply { + layoutParams = + LinearLayout.LayoutParams( + targetEmojiView.width * getNumberOfColumns() / 2, + targetEmojiView.height + ) + } + } else if (hasLeftSkintone()) { + drawImageView( + /* row= */ 0, + /*column=*/ selectedLeftSkintone, + /* applyGrayTint= */ false + ) + } else if (hasRightSkintone()) { + drawImageView( + /* row= */ 1, + /*column=*/ selectedRightSkintone, + /* applyGrayTint= */ false + ) + } else { + drawImageView(/* row= */ 0, /* column= */ 0, /* applyGrayTint= */ true) + } + } + + private fun drawImageView(row: Int, column: Int, applyGrayTint: Boolean) { + inflater + .inflate(R.layout.emoji_picker_popup_image_view, resultRow) + .findViewById(R.id.emoji_picker_popup_image_view) + .apply { + layoutParams = LinearLayout.LayoutParams(0, targetEmojiView.height, 1f) + setImageDrawable(getDrawableRes(context, row, column)) + if (applyGrayTint) { + imageTintList = ColorStateList.valueOf(Color.GRAY) + } + + var contentDescriptionRow = selectedLeftSkintone + var contentDescriptionColumn = selectedRightSkintone + if (hasLeftSkintone()) { + contentDescriptionRow = 0 + contentDescriptionColumn = selectedLeftSkintone + } else if (hasRightSkintone()) { + contentDescriptionRow = 1 + contentDescriptionColumn = selectedRightSkintone + } + contentDescription = + getImageContentDescription( + context, + contentDescriptionRow, + contentDescriptionColumn + ) + } + } + + override fun addLayoutFooter() { + inflater.inflate(R.layout.emoji_picker_popup_emoji_view, resultRow) + val layout = resultRow.getChildAt(0) as LinearLayout + layout.findViewById(R.id.emoji_picker_popup_emoji_view).apply { + willDrawVariantIndicator = false + emoji = variants[0] + layoutParams = LinearLayout.LayoutParams(targetEmojiView.width, targetEmojiView.height) + isClickable = true + setOnClickListener(emojiViewOnClickListener) + } + layout.findViewById(R.id.emoji_picker_popup_emoji_view_wrapper).apply { + layoutParams = + LinearLayout.LayoutParams( + targetEmojiView.width * getNumberOfColumns() / 2, + targetEmojiView.height + ) + } + processResultView() + popupView.addView(resultRow) + } + + override fun getNumberOfRows(): Int { + // Add one extra row for the neutral skin tone combination + return LAYOUT_ROWS + 1 + } + + override fun getNumberOfColumns(): Int { + return LAYOUT_COLUMNS + } + + private fun getActualNumberOfRows(): Int { + return LAYOUT_ROWS + } + + private fun hasLeftSkintone(): Boolean { + return selectedLeftSkintone != -1 + } + + private fun hasRightSkintone(): Boolean { + return selectedRightSkintone != -1 + } + + private fun getDrawableRes(context: Context, row: Int, column: Int): Drawable? { + val resArray: ImmutableIntArray? = SKIN_TONES_EMOJI_TO_RESOURCES[variants[0]] + if (resArray != null) { + val contextThemeWrapper = ContextThemeWrapper(context, VARIANT_STYLES[column]) + return ResourcesCompat.getDrawable( + context.resources, + resArray[row], + contextThemeWrapper.getTheme() + ) + } + return null + } + + private fun getImageContentDescription(context: Context, row: Int, column: Int): String { + return context.getString( + R.string.emoji_variant_content_desc_template, + context.getString(getSkintoneStringRes(/* isLeft= */ true, row, column)), + context.getString(getSkintoneStringRes(/* isLeft= */ false, row, column)) + ) + } + + @StringRes + private fun getSkintoneStringRes(isLeft: Boolean, row: Int, column: Int): Int { + // When there is no column, the selected position -1 will be passed in as column. + if (column == -1) { + return R.string.emoji_skin_tone_shadow_content_desc + } + return if (isLeft) { + if (row == 0) SKIN_TONE_CONTENT_DESC_RES_IDS[column] + else R.string.emoji_skin_tone_shadow_content_desc + } else { + if (row == 0) R.string.emoji_skin_tone_shadow_content_desc + else SKIN_TONE_CONTENT_DESC_RES_IDS[column] + } + } + + companion object { + private const val TAG = "MultiSkintoneDesign" + private const val LAYOUT_ROWS = 2 + private const val LAYOUT_COLUMNS = 5 + + private val SKIN_TONE_CONTENT_DESC_RES_IDS = + ImmutableIntArray.of( + R.string.emoji_skin_tone_light_content_desc, + R.string.emoji_skin_tone_medium_light_content_desc, + R.string.emoji_skin_tone_medium_content_desc, + R.string.emoji_skin_tone_medium_dark_content_desc, + R.string.emoji_skin_tone_dark_content_desc + ) + + private val VARIANT_STYLES = + ImmutableIntArray.of( + R.style.EmojiSkintoneSelectorLight, + R.style.EmojiSkintoneSelectorMediumLight, + R.style.EmojiSkintoneSelectorMedium, + R.style.EmojiSkintoneSelectorMediumDark, + R.style.EmojiSkintoneSelectorDark + ) + + /** + * Map from emoji that use the square layout strategy with skin tone swatches or rectangle + * strategy to their resources. + */ + private val SKIN_TONES_EMOJI_TO_RESOURCES = + ImmutableMap.Builder() + .put( + "🤝", + ImmutableIntArray.of( + R.drawable.handshake_skintone_shadow, + R.drawable.handshake_shadow_skintone + ) + ) + .put( + "👭", + ImmutableIntArray.of( + R.drawable.holding_women_skintone_shadow, + R.drawable.holding_women_shadow_skintone + ) + ) + .put( + "👫", + ImmutableIntArray.of( + R.drawable.holding_woman_man_skintone_shadow, + R.drawable.holding_woman_man_shadow_skintone + ) + ) + .put( + "👬", + ImmutableIntArray.of( + R.drawable.holding_men_skintone_shadow, + R.drawable.holding_men_shadow_skintone + ) + ) + .put( + "🧑‍🤝‍🧑", + ImmutableIntArray.of( + R.drawable.holding_people_skintone_shadow, + R.drawable.holding_people_shadow_skintone + ) + ) + .put( + "💏", + ImmutableIntArray.of( + R.drawable.kiss_people_skintone_shadow, + R.drawable.kiss_people_shadow_skintone + ) + ) + .put( + "👩‍❤️‍💋‍👨", + ImmutableIntArray.of( + R.drawable.kiss_woman_man_skintone_shadow, + R.drawable.kiss_woman_man_shadow_skintone + ) + ) + .put( + "👨‍❤️‍💋‍👨", + ImmutableIntArray.of( + R.drawable.kiss_men_skintone_shadow, + R.drawable.kiss_men_shadow_skintone + ) + ) + .put( + "👩‍❤️‍💋‍👩", + ImmutableIntArray.of( + R.drawable.kiss_women_skintone_shadow, + R.drawable.kiss_women_shadow_skintone + ) + ) + .put( + "💑", + ImmutableIntArray.of( + R.drawable.couple_heart_people_skintone_shadow, + R.drawable.couple_heart_people_shadow_skintone + ) + ) + .put( + "👩‍❤️‍👨", + ImmutableIntArray.of( + R.drawable.couple_heart_woman_man_skintone_shadow, + R.drawable.couple_heart_woman_man_shadow_skintone + ) + ) + .put( + "👨‍❤️‍👨", + ImmutableIntArray.of( + R.drawable.couple_heart_men_skintone_shadow, + R.drawable.couple_heart_men_shadow_skintone + ) + ) + .put( + "👩‍❤️‍👩", + ImmutableIntArray.of( + R.drawable.couple_heart_women_skintone_shadow, + R.drawable.couple_heart_women_shadow_skintone + ) + ) + .build() + } +} diff --git a/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupSquareDesign.kt b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupSquareDesign.kt new file mode 100644 index 000000000..0472995f0 --- /dev/null +++ b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupSquareDesign.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.rishabh.emojipicker + +import android.content.Context +import android.view.View +import android.widget.LinearLayout + +/** Emoji picker popup view with square design. */ +internal class EmojiPickerPopupSquareDesign( + override val context: Context, + override val targetEmojiView: View, + override val variants: List, + override val popupView: LinearLayout, + override val emojiViewOnClickListener: View.OnClickListener +) : EmojiPickerPopupDesign() { + init { + template = SQUARE_LAYOUT_TEMPLATE + } + + override fun getNumberOfRows(): Int { + return SQUARE_LAYOUT_TEMPLATE.size + } + + override fun getNumberOfColumns(): Int { + return SQUARE_LAYOUT_TEMPLATE[0].size + } + + companion object { + /** + * Square variant layout template without skin tone. 0 : a place holder Positive number is + * the index + 1 in the variant array + */ + private val SQUARE_LAYOUT_TEMPLATE = + arrayOf( + intArrayOf(0, 2, 3, 4, 5, 6), + intArrayOf(0, 7, 8, 9, 10, 11), + intArrayOf(0, 12, 13, 14, 15, 16), + intArrayOf(0, 17, 18, 19, 20, 21), + intArrayOf(1, 22, 23, 24, 25, 26) + ) + } +} diff --git a/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupView.kt b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupView.kt new file mode 100644 index 000000000..a6ca815f7 --- /dev/null +++ b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupView.kt @@ -0,0 +1,134 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.rishabh.emojipicker + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import android.widget.FrameLayout +import android.widget.LinearLayout + +/** Popup view for emoji picker to show emoji variants. */ +internal class EmojiPickerPopupView +@JvmOverloads +constructor( + context: Context, + attrs: AttributeSet?, + defStyleAttr: Int = 0, + private val targetEmojiView: View, + private val targetEmojiItem: EmojiViewItem, + private val emojiViewOnClickListener: OnClickListener +) : FrameLayout(context, attrs, defStyleAttr) { + + private val variants = targetEmojiItem.variants + private val targetEmoji = targetEmojiItem.emoji + private val popupView: LinearLayout + private val popupDesign: EmojiPickerPopupDesign + + init { + popupView = + inflate(context, R.layout.variant_popup, /* root= */ null) + .findViewById(R.id.variant_popup) + val layout = getLayout() + popupDesign = + when (layout) { + Layout.FLAT -> + EmojiPickerPopupFlatDesign( + context, + targetEmojiView, + variants, + popupView, + emojiViewOnClickListener + ) + Layout.SQUARE -> + EmojiPickerPopupSquareDesign( + context, + targetEmojiView, + variants, + popupView, + emojiViewOnClickListener + ) + Layout.SQUARE_WITH_SKIN_TONE_CIRCLE -> + EmojiPickerPopupMultiSkintoneDesign( + context, + targetEmojiView, + variants, + popupView, + emojiViewOnClickListener, + targetEmoji + ) + Layout.BIDIRECTIONAL -> + EmojiPickerPopupBidirectionalDesign( + context, + targetEmojiView, + variants, + popupView, + emojiViewOnClickListener + ) + } + popupDesign.addLayoutHeader() + popupDesign.addRowsToPopupView() + popupDesign.addLayoutFooter() + addView(popupView) + } + + fun getPopupViewWidth(): Int { + return popupDesign.getNumberOfColumns() * targetEmojiView.width + + popupView.paddingStart + + popupView.paddingEnd + } + + fun getPopupViewHeight(): Int { + return popupDesign.getNumberOfRows() * targetEmojiView.height + + popupView.paddingTop + + popupView.paddingBottom + } + + private fun getLayout(): Layout { + if (variants.size == SQUARE_LAYOUT_VARIANT_COUNT) + if (SQUARE_LAYOUT_EMOJI_NO_SKIN_TONE.contains(variants[0])) return Layout.SQUARE + else return Layout.SQUARE_WITH_SKIN_TONE_CIRCLE + else if (variants.size == BIDIRECTIONAL_VARIANTS_COUNT) return Layout.BIDIRECTIONAL + else return Layout.FLAT + } + + companion object { + private enum class Layout { + FLAT, + SQUARE, + SQUARE_WITH_SKIN_TONE_CIRCLE, + BIDIRECTIONAL + } + + /** + * The number of variants expected when using a square layout strategy. Square layouts are + * comprised of a 5x5 grid + the base variant. + */ + private const val SQUARE_LAYOUT_VARIANT_COUNT = 26 + + /** + * The number of variants expected when using a bidirectional layout strategy. Bidirectional + * layouts are comprised of bidirectional icon and a 3x6 grid with left direction emojis as + * default. After clicking the bidirectional icon, it switches to a bidirectional icon and a + * 3x6 grid with right direction emojis. + */ + private const val BIDIRECTIONAL_VARIANTS_COUNT = 36 + + // Set of emojis that use the square layout without skin tone swatches. + private val SQUARE_LAYOUT_EMOJI_NO_SKIN_TONE = setOf("👪") + } +} diff --git a/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupViewController.kt b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupViewController.kt new file mode 100644 index 000000000..36c4d76cb --- /dev/null +++ b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupViewController.kt @@ -0,0 +1,70 @@ +package com.rishabh.emojipicker + + + +import android.content.Context +import android.view.Gravity +import android.view.View +import android.view.ViewGroup.LayoutParams +import android.view.WindowManager +import android.widget.PopupWindow +import android.widget.Toast +import kotlin.math.roundToInt + +/** + * Default controller class for emoji picker popup view. + * + *

Shows the popup view above the target Emoji. View under control is a {@code + * EmojiPickerPopupView}. + */ +internal class EmojiPickerPopupViewController( + private val context: Context, + private val emojiPickerPopupView: EmojiPickerPopupView, + private val clickedEmojiView: View +) { + private val popupWindow: PopupWindow = + PopupWindow( + emojiPickerPopupView, + LayoutParams.WRAP_CONTENT, + LayoutParams.WRAP_CONTENT, + /* focusable= */ false + ) + + fun show() { + popupWindow.apply { + val location = IntArray(2) + clickedEmojiView.getLocationInWindow(location) + // Make the popup view center align with the target emoji view. + val x = + location[0] + clickedEmojiView.width / 2f - + emojiPickerPopupView.getPopupViewWidth() / 2f + val y = location[1] - emojiPickerPopupView.getPopupViewHeight() + // Set background drawable so that the popup window is dismissed properly when clicking + // outside / scrolling for API < 23. + setBackgroundDrawable(context.getDrawable(R.drawable.popup_view_rounded_background)) + isOutsideTouchable = true + isTouchable = true + animationStyle = R.style.VariantPopupAnimation + elevation = + clickedEmojiView.context.resources + .getDimensionPixelSize(R.dimen.emoji_picker_popup_view_elevation) + .toFloat() + try { + showAtLocation(clickedEmojiView, Gravity.NO_GRAVITY, x.roundToInt(), y) + } catch (e: WindowManager.BadTokenException) { + Toast.makeText( + context, + "Don't use EmojiPickerView inside a Popup", + Toast.LENGTH_LONG + ) + .show() + } + } + } + + fun dismiss() { + if (popupWindow.isShowing) { + popupWindow.dismiss() + } + } +} diff --git a/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerView.kt b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerView.kt new file mode 100644 index 000000000..14be78680 --- /dev/null +++ b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiPickerView.kt @@ -0,0 +1,445 @@ + + +package com.rishabh.emojipicker + +import android.content.Context +import android.content.res.TypedArray +import android.util.AttributeSet +import android.view.View +import android.view.ViewGroup +import android.widget.FrameLayout +import androidx.core.util.Consumer +import androidx.core.view.ViewCompat +import com.rishabh.emojipicker.EmojiPickerConstants.DEFAULT_MAX_RECENT_ITEM_ROWS +import androidx.emoji2.text.EmojiCompat +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import kotlin.coroutines.EmptyCoroutineContext +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext + +/** + * The emoji picker view that provides up-to-date emojis in a vertical scrollable view with a + * clickable horizontal header. + */ +class EmojiPickerView +@JvmOverloads +constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : + FrameLayout(context, attrs, defStyleAttr) { + + internal companion object { + internal var emojiCompatLoaded: Boolean = false + } + + private var _emojiGridRows: Float? = null + /** + * The number of rows of the emoji picker. + * + * Optional field. If not set, the value will be calculated based on parent view height and + * [emojiGridColumns]. Float value indicates that the picker could display the last row + * partially, so the users get the idea that they can scroll down for more contents. + * + * @attr ref androidx.emoji2.emojipicker.R.styleable.EmojiPickerView_emojiGridRows + */ + var emojiGridRows: Float + get() = _emojiGridRows ?: -1F + set(value) { + _emojiGridRows = value.takeIf { it > 0 } + // Refresh when emojiGridRows is reset + if (isLaidOut) { + showEmojiPickerView() + } + } + + /** + * The number of columns of the emoji picker. + * + * Default value([EmojiPickerConstants.DEFAULT_BODY_COLUMNS]: 9) will be used if + * emojiGridColumns is set to non-positive value. + * + * @attr ref androidx.emoji2.emojipicker.R.styleable.EmojiPickerView_emojiGridColumns + */ + var emojiGridColumns: Int = EmojiPickerConstants.DEFAULT_BODY_COLUMNS + set(value) { + field = value.takeIf { it > 0 } ?: EmojiPickerConstants.DEFAULT_BODY_COLUMNS + // Refresh when emojiGridColumns is reset + if (isLaidOut) { + showEmojiPickerView() + } + } + + private val stickyVariantProvider = StickyVariantProvider(context) + private val scope = CoroutineScope(EmptyCoroutineContext) + + private var recentEmojiProvider: RecentEmojiProvider = DefaultRecentEmojiProvider(context) + private var recentNeedsRefreshing: Boolean = true + private val recentItems: MutableList = mutableListOf() + private lateinit var recentItemGroup: ItemGroup + + private lateinit var emojiPickerItems: EmojiPickerItems + private lateinit var bodyAdapter: EmojiPickerBodyAdapter + + private var onEmojiPickedListener: Consumer? = null + + init { + val typedArray: TypedArray = + context.obtainStyledAttributes(attrs, R.styleable.EmojiPickerView, 0, 0) + _emojiGridRows = + with(R.styleable.EmojiPickerView_emojiGridRows) { + if (typedArray.hasValue(this)) { + typedArray.getFloat(this, 0F) + } else null + } + emojiGridColumns = + typedArray.getInt( + R.styleable.EmojiPickerView_emojiGridColumns, + EmojiPickerConstants.DEFAULT_BODY_COLUMNS + ) + typedArray.recycle() + + if (EmojiCompat.isConfigured()) { + when (EmojiCompat.get().loadState) { + EmojiCompat.LOAD_STATE_SUCCEEDED -> emojiCompatLoaded = true + EmojiCompat.LOAD_STATE_LOADING, + EmojiCompat.LOAD_STATE_DEFAULT -> + EmojiCompat.get() + .registerInitCallback( + object : EmojiCompat.InitCallback() { + override fun onInitialized() { + emojiCompatLoaded = true + scope.launch(Dispatchers.IO) { + BundledEmojiListLoader.load(context) + withContext(Dispatchers.Main) { + emojiPickerItems = buildEmojiPickerItems() + bodyAdapter.notifyDataSetChanged() + } + } + } + + override fun onFailed(throwable: Throwable?) {} + } + ) + } + } + scope.launch(Dispatchers.IO) { + val load = launch { BundledEmojiListLoader.load(context) } + refreshRecent() + load.join() + + withContext(Dispatchers.Main) { showEmojiPickerView() } + } + } + + private fun createEmojiPickerBodyAdapter(): EmojiPickerBodyAdapter { + return EmojiPickerBodyAdapter( + context, + emojiGridColumns, + _emojiGridRows, + stickyVariantProvider, + emojiPickerItemsProvider = { emojiPickerItems }, + onEmojiPickedListener = { emojiViewItem -> + onEmojiPickedListener?.accept(emojiViewItem) + recentEmojiProvider.recordSelection(emojiViewItem.emoji) + recentNeedsRefreshing = true + } + ) + } + + internal fun buildEmojiPickerItems() = + EmojiPickerItems( + buildList { + add( + ItemGroup( + R.drawable.quantum_gm_ic_access_time_filled_vd_theme_24, + CategoryTitle(context.getString(R.string.emoji_category_recent)), + recentItems, + maxContentItemCount = DEFAULT_MAX_RECENT_ITEM_ROWS * emojiGridColumns, + emptyPlaceholderItem = + PlaceholderText( + context.getString(R.string.emoji_empty_recent_category) + ) + ) + .also { recentItemGroup = it } + ) + + for ((i, category) in + BundledEmojiListLoader.getCategorizedEmojiData().withIndex()) { + add( + ItemGroup( + category.headerIconId, + CategoryTitle(category.categoryName), + category.emojiDataList.mapIndexed { j, emojiData -> + EmojiViewData( + stickyVariantProvider[emojiData.emoji], + dataIndex = i + j + ) + }, + ) + ) + } + } + ) + + private fun showEmojiPickerView() { + emojiPickerItems = buildEmojiPickerItems() + + val bodyLayoutManager = + GridLayoutManager( + context, + emojiGridColumns, + LinearLayoutManager.VERTICAL, + /* reverseLayout = */ false + ) + .apply { + spanSizeLookup = + object : GridLayoutManager.SpanSizeLookup() { + override fun getSpanSize(position: Int): Int { + return when (emojiPickerItems.getBodyItem(position).itemType) { + ItemType.CATEGORY_TITLE, + ItemType.PLACEHOLDER_TEXT -> emojiGridColumns + else -> 1 + } + } + } + } + + val headerAdapter = + EmojiPickerHeaderAdapter( + context, + emojiPickerItems, + onHeaderIconClicked = { + with(emojiPickerItems.firstItemPositionByGroupIndex(it)) { + if (this == emojiPickerItems.groupRange(recentItemGroup).first) { + scope.launch { refreshRecent() } + } + bodyLayoutManager.scrollToPositionWithOffset(this, 0) + // The scroll position change will not be reflected until the next layout + // call, + // so force a new layout call here. + invalidate() + } + } + ) + + // clear view's children in case of resetting layout + super.removeAllViews() + with(inflate(context, R.layout.emoji_picker, this)) { + // set headerView + ViewCompat.requireViewById(this, R.id.emoji_picker_header).apply { + layoutManager = + object : LinearLayoutManager(context, HORIZONTAL, /* reverseLayout= */ false) { + override fun checkLayoutParams(lp: RecyclerView.LayoutParams): Boolean { + lp.width = + (width - paddingStart - paddingEnd) / emojiPickerItems.numGroups + return true + } + } + adapter = headerAdapter + } + + // set bodyView + ViewCompat.requireViewById(this, R.id.emoji_picker_body).apply { + layoutManager = bodyLayoutManager + adapter = + createEmojiPickerBodyAdapter() + .apply { setHasStableIds(true) } + .also { bodyAdapter = it } + addOnScrollListener( + object : RecyclerView.OnScrollListener() { + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + super.onScrolled(recyclerView, dx, dy) + headerAdapter.selectedGroupIndex = + emojiPickerItems.groupIndexByItemPosition( + bodyLayoutManager.findFirstCompletelyVisibleItemPosition() + ) + if ( + recentNeedsRefreshing && + bodyLayoutManager.findFirstVisibleItemPosition() !in + emojiPickerItems.groupRange(recentItemGroup) + ) { + scope.launch { refreshRecent() } + } + } + } + ) + // Disable item insertion/deletion animation. This keeps view holder unchanged when + // item updates. + itemAnimator = null + setRecycledViewPool( + RecyclerView.RecycledViewPool().apply { + setMaxRecycledViews( + ItemType.EMOJI.ordinal, + EmojiPickerConstants.EMOJI_VIEW_POOL_SIZE + ) + } + ) + } + } + } + + internal suspend fun refreshRecent() { + if (!recentNeedsRefreshing) { + return + } + val oldGroupSize = if (::recentItemGroup.isInitialized) recentItemGroup.size else 0 + val recent = recentEmojiProvider.getRecentEmojiList() + withContext(Dispatchers.Main) { + recentItems.clear() + recentItems.addAll( + recent.map { + EmojiViewData( + it, + updateToSticky = false, + ) + } + ) + if (::emojiPickerItems.isInitialized) { + val range = emojiPickerItems.groupRange(recentItemGroup) + if (recentItemGroup.size > oldGroupSize) { + bodyAdapter.notifyItemRangeInserted( + range.first + oldGroupSize, + recentItemGroup.size - oldGroupSize + ) + } else if (recentItemGroup.size < oldGroupSize) { + bodyAdapter.notifyItemRangeRemoved( + range.first + recentItemGroup.size, + oldGroupSize - recentItemGroup.size + ) + } + bodyAdapter.notifyItemRangeChanged( + range.first, + minOf(oldGroupSize, recentItemGroup.size) + ) + recentNeedsRefreshing = false + } + } + } + + /** + * This function is used to set the custom behavior after clicking on an emoji icon. Clients + * could specify their own behavior inside this function. + */ + fun setOnEmojiPickedListener(onEmojiPickedListener: Consumer?) { + this.onEmojiPickedListener = onEmojiPickedListener + } + + fun setRecentEmojiProvider(recentEmojiProvider: RecentEmojiProvider) { + this.recentEmojiProvider = recentEmojiProvider + scope.launch { + recentNeedsRefreshing = true + refreshRecent() + } + } + + /** + * The following functions disallow clients to add view to the EmojiPickerView + * + * @param child the child view to be added + * @throws UnsupportedOperationException + */ + override fun addView(child: View?) { + if (childCount > 0) + throw UnsupportedOperationException(EmojiPickerConstants.ADD_VIEW_EXCEPTION_MESSAGE) + else super.addView(child) + } + + /** + * @param child + * @param params + * @throws UnsupportedOperationException + */ + override fun addView(child: View?, params: ViewGroup.LayoutParams?) { + if (childCount > 0) + throw UnsupportedOperationException(EmojiPickerConstants.ADD_VIEW_EXCEPTION_MESSAGE) + else super.addView(child, params) + } + + /** + * @param child + * @param index + * @throws UnsupportedOperationException + */ + override fun addView(child: View?, index: Int) { + if (childCount > 0) + throw UnsupportedOperationException(EmojiPickerConstants.ADD_VIEW_EXCEPTION_MESSAGE) + else super.addView(child, index) + } + + /** + * @param child + * @param index + * @param params + * @throws UnsupportedOperationException + */ + override fun addView(child: View?, index: Int, params: ViewGroup.LayoutParams?) { + if (childCount > 0) + throw UnsupportedOperationException(EmojiPickerConstants.ADD_VIEW_EXCEPTION_MESSAGE) + else super.addView(child, index, params) + } + + /** + * @param child + * @param width + * @param height + * @throws UnsupportedOperationException + */ + override fun addView(child: View?, width: Int, height: Int) { + if (childCount > 0) + throw UnsupportedOperationException(EmojiPickerConstants.ADD_VIEW_EXCEPTION_MESSAGE) + else super.addView(child, width, height) + } + + /** + * The following functions disallow clients to remove view from the EmojiPickerView + * + * @throws UnsupportedOperationException + */ + override fun removeAllViews() { + throw UnsupportedOperationException(EmojiPickerConstants.REMOVE_VIEW_EXCEPTION_MESSAGE) + } + + /** + * @param child + * @throws UnsupportedOperationException + */ + override fun removeView(child: View?) { + throw UnsupportedOperationException(EmojiPickerConstants.REMOVE_VIEW_EXCEPTION_MESSAGE) + } + + /** + * @param index + * @throws UnsupportedOperationException + */ + override fun removeViewAt(index: Int) { + throw UnsupportedOperationException(EmojiPickerConstants.REMOVE_VIEW_EXCEPTION_MESSAGE) + } + + /** + * @param child + * @throws UnsupportedOperationException + */ + override fun removeViewInLayout(child: View?) { + throw UnsupportedOperationException(EmojiPickerConstants.REMOVE_VIEW_EXCEPTION_MESSAGE) + } + + /** + * @param start + * @param count + * @throws UnsupportedOperationException + */ + override fun removeViews(start: Int, count: Int) { + throw UnsupportedOperationException(EmojiPickerConstants.REMOVE_VIEW_EXCEPTION_MESSAGE) + } + + /** + * @param start + * @param count + * @throws UnsupportedOperationException + */ + override fun removeViewsInLayout(start: Int, count: Int) { + throw UnsupportedOperationException(EmojiPickerConstants.REMOVE_VIEW_EXCEPTION_MESSAGE) + } +} diff --git a/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiView.kt b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiView.kt new file mode 100644 index 000000000..835881ae8 --- /dev/null +++ b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiView.kt @@ -0,0 +1,173 @@ + + +package com.rishabh.emojipicker + +import android.content.Context +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.graphics.Rect +import android.os.Build +import android.text.Layout +import android.text.Spanned +import android.text.StaticLayout +import android.text.TextPaint +import android.util.AttributeSet +import android.util.TypedValue +import android.view.View +import androidx.annotation.RequiresApi +import androidx.core.graphics.applyCanvas +import androidx.emoji2.text.EmojiCompat + +/** A customized view to support drawing emojis asynchronously. */ +internal class EmojiView +@JvmOverloads +constructor( + context: Context, + attrs: AttributeSet? = null, +) : View(context, attrs) { + + companion object { + private const val EMOJI_DRAW_TEXT_SIZE_SP = 30 + } + + init { + background = context.getDrawable(R.drawable.ripple_emoji_view) + importantForAccessibility = IMPORTANT_FOR_ACCESSIBILITY_YES + } + + internal var willDrawVariantIndicator: Boolean = true + + private val textPaint = + TextPaint(Paint.ANTI_ALIAS_FLAG or Paint.FILTER_BITMAP_FLAG).apply { + textSize = + TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_SP, + EMOJI_DRAW_TEXT_SIZE_SP.toFloat(), + context.resources.displayMetrics + ) + } + + private val offscreenCanvasBitmap: Bitmap = + with(textPaint.fontMetricsInt) { + val size = bottom - top + Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888) + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + val size = + minOf(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec)) - + context.resources.getDimensionPixelSize(R.dimen.emoji_picker_emoji_view_padding) + setMeasuredDimension(size, size) + } + + override fun draw(canvas: Canvas) { + super.draw(canvas) + canvas.run { + save() + scale( + width.toFloat() / offscreenCanvasBitmap.width, + height.toFloat() / offscreenCanvasBitmap.height + ) + drawBitmap(offscreenCanvasBitmap, 0f, 0f, null) + restore() + } + } + + var emoji: CharSequence? = null + set(value) { + field = value + post { + if (value != null) { + if (value == this.emoji) { + drawEmoji( + if (EmojiPickerView.emojiCompatLoaded) + EmojiCompat.get().process(value) ?: value + else value, + drawVariantIndicator = + willDrawVariantIndicator && + BundledEmojiListLoader.getEmojiVariantsLookup() + .containsKey(value) + ) + contentDescription = value + } + invalidate() + } else { + offscreenCanvasBitmap.eraseColor(Color.TRANSPARENT) + } + } + } + + private fun drawEmoji(emoji: CharSequence, drawVariantIndicator: Boolean) { + offscreenCanvasBitmap.eraseColor(Color.TRANSPARENT) + offscreenCanvasBitmap.applyCanvas { + if (emoji is Spanned) { + createStaticLayout(emoji, width).draw(this) + } else { + val textWidth = textPaint.measureText(emoji, 0, emoji.length) + drawText( + emoji, + /* start = */ 0, + /* end = */ emoji.length, + /* x = */ (width - textWidth) / 2, + /* y = */ -textPaint.fontMetrics.top, + textPaint, + ) + } + if (drawVariantIndicator) { + context + .getDrawable(R.drawable.variant_availability_indicator) + ?.apply { + val canvasWidth = this@applyCanvas.width + val canvasHeight = this@applyCanvas.height + val indicatorWidth = + context.resources.getDimensionPixelSize( + R.dimen.variant_availability_indicator_width + ) + val indicatorHeight = + context.resources.getDimensionPixelSize( + R.dimen.variant_availability_indicator_height + ) + bounds = + Rect( + canvasWidth - indicatorWidth, + canvasHeight - indicatorHeight, + canvasWidth, + canvasHeight + ) + }!! + .draw(this) + } + } + } + + @RequiresApi(23) + internal object Api23Impl { + fun createStaticLayout(emoji: Spanned, textPaint: TextPaint, width: Int): StaticLayout = + StaticLayout.Builder.obtain(emoji, 0, emoji.length, textPaint, width) + .apply { + setAlignment(Layout.Alignment.ALIGN_CENTER) + setLineSpacing(/* spacingAdd= */ 0f, /* spacingMult= */ 1f) + setIncludePad(false) + } + .build() + } + + private fun createStaticLayout(emoji: Spanned, width: Int): StaticLayout { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + return Api23Impl.createStaticLayout(emoji, textPaint, width) + } else { + @Suppress("DEPRECATION") + return StaticLayout( + emoji, + textPaint, + width, + Layout.Alignment.ALIGN_CENTER, + /* spacingmult = */ 1f, + /* spacingadd = */ 0f, + /* includepad = */ false, + ) + } + } +} diff --git a/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiViewHolder.kt b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiViewHolder.kt new file mode 100644 index 000000000..01c4c358b --- /dev/null +++ b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiViewHolder.kt @@ -0,0 +1,81 @@ + + +package com.rishabh.emojipicker + +import android.content.Context +import android.view.View +import android.view.View.OnLongClickListener +import android.view.ViewGroup.LayoutParams +import android.view.accessibility.AccessibilityEvent +import androidx.recyclerview.widget.RecyclerView.ViewHolder + +/** A [ViewHolder] containing an emoji view and emoji data. */ +internal class EmojiViewHolder( + context: Context, + width: Int, + height: Int, + private val stickyVariantProvider: StickyVariantProvider, + private val onEmojiPickedListener: EmojiViewHolder.(EmojiViewItem) -> Unit, + private val onEmojiPickedFromPopupListener: EmojiViewHolder.(String) -> Unit +) : ViewHolder(EmojiView(context)) { + private val onEmojiLongClickListener: OnLongClickListener = + OnLongClickListener { targetEmojiView -> + showEmojiPopup(context, targetEmojiView) + } + + private val emojiView: EmojiView = + (itemView as EmojiView).apply { + layoutParams = LayoutParams(width, height) + isClickable = true + setOnClickListener { + it.sendAccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT) + onEmojiPickedListener(emojiViewItem) + } + } + private lateinit var emojiViewItem: EmojiViewItem + private lateinit var emojiPickerPopupViewController: EmojiPickerPopupViewController + + fun bindEmoji( + emoji: String, + ) { + emojiView.emoji = emoji + emojiViewItem = makeEmojiViewItem(emoji) + + if (emojiViewItem.variants.isNotEmpty()) { + emojiView.setOnLongClickListener(onEmojiLongClickListener) + emojiView.isLongClickable = true + } else { + emojiView.setOnLongClickListener(null) + emojiView.isLongClickable = false + } + } + + private fun showEmojiPopup(context: Context, clickedEmojiView: View): Boolean { + val emojiPickerPopupView = + EmojiPickerPopupView( + context, + /* attrs= */ null, + targetEmojiView = clickedEmojiView, + targetEmojiItem = emojiViewItem, + emojiViewOnClickListener = { view -> + val emojiPickedInPopup = (view as EmojiView).emoji.toString() + onEmojiPickedFromPopupListener(emojiPickedInPopup) + onEmojiPickedListener(makeEmojiViewItem(emojiPickedInPopup)) + // variants[0] is always the base (i.e., primary) emoji + stickyVariantProvider.update(emojiViewItem.variants[0], emojiPickedInPopup) + emojiPickerPopupViewController.dismiss() + // Hover on the base emoji after popup dismissed + clickedEmojiView.sendAccessibilityEvent( + AccessibilityEvent.TYPE_VIEW_HOVER_ENTER + ) + } + ) + emojiPickerPopupViewController = + EmojiPickerPopupViewController(context, emojiPickerPopupView, clickedEmojiView) + emojiPickerPopupViewController.show() + return true + } + + private fun makeEmojiViewItem(emoji: String) = + EmojiViewItem(emoji, BundledEmojiListLoader.getEmojiVariantsLookup()[emoji] ?: listOf()) +} diff --git a/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiViewItem.kt b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiViewItem.kt new file mode 100644 index 000000000..35ac58ae8 --- /dev/null +++ b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/EmojiViewItem.kt @@ -0,0 +1,11 @@ + + +package com.rishabh.emojipicker + +/** + * [EmojiViewItem] is a class holding the displayed emoji and its emoji variants + * + * @param emoji Used to represent the displayed emoji of the [EmojiViewItem]. + * @param variants Used to represent the corresponding emoji variants of this base emoji. + */ +class EmojiViewItem(val emoji: String, val variants: List) diff --git a/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/ItemViewData.kt b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/ItemViewData.kt new file mode 100644 index 000000000..2afefc9fc --- /dev/null +++ b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/ItemViewData.kt @@ -0,0 +1,32 @@ + + +package com.rishabh.emojipicker + +internal enum class ItemType { + CATEGORY_TITLE, + PLACEHOLDER_TEXT, + EMOJI, +} + +/** Represents an item within the body RecyclerView. */ +internal sealed class ItemViewData(val itemType: ItemType) { + val viewType = itemType.ordinal +} + +/** Title of each category. */ +internal data class CategoryTitle(val title: String) : ItemViewData(ItemType.CATEGORY_TITLE) + +/** Text to display when the category contains no items. */ +internal data class PlaceholderText(val text: String) : ItemViewData(ItemType.PLACEHOLDER_TEXT) + +/** Represents an emoji. */ +internal data class EmojiViewData( + var emoji: String, + val updateToSticky: Boolean = true, + // Needed to ensure uniqueness since we enabled stable Id. + val dataIndex: Int = 0 +) : ItemViewData(ItemType.EMOJI) + +internal object Extensions { + internal fun Int.toItemType() = ItemType.values()[this] +} diff --git a/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/RecentEmojiAsyncProvider.kt b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/RecentEmojiAsyncProvider.kt new file mode 100644 index 000000000..5f599e721 --- /dev/null +++ b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/RecentEmojiAsyncProvider.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.rishabh.emojipicker + +import com.google.common.util.concurrent.ListenableFuture +import kotlinx.coroutines.guava.await + +/** + * A interface equivalent to [RecentEmojiProvider] that allows java clients to override the + * [ListenableFuture] based function [getRecentEmojiListAsync] in order to provide recent emojis. + */ +interface RecentEmojiAsyncProvider { + fun recordSelection(emoji: String) + + fun getRecentEmojiListAsync(): ListenableFuture> +} + +/** An adapter for the [RecentEmojiAsyncProvider]. */ +class RecentEmojiProviderAdapter(private val recentEmojiAsyncProvider: RecentEmojiAsyncProvider) : + RecentEmojiProvider { + override fun recordSelection(emoji: String) { + recentEmojiAsyncProvider.recordSelection(emoji) + } + + override suspend fun getRecentEmojiList() = + recentEmojiAsyncProvider.getRecentEmojiListAsync().await() +} diff --git a/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/RecentEmojiProvider.kt b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/RecentEmojiProvider.kt new file mode 100644 index 000000000..8362822f9 --- /dev/null +++ b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/RecentEmojiProvider.kt @@ -0,0 +1,19 @@ + + +package com.rishabh.emojipicker + +/** An interface to provide recent emoji list. */ +interface RecentEmojiProvider { + /** + * Records an emoji into recent emoji list. This fun will be called when an emoji is selected. + * Clients could specify the behavior to record recently used emojis.(e.g. click frequency). + */ + fun recordSelection(emoji: String) + + /** + * Returns a list of recent emojis. Default behavior: The most recently used emojis will be + * displayed first. Clients could also specify the behavior such as displaying the emojis from + * high click frequency to low click frequency. + */ + suspend fun getRecentEmojiList(): List +} diff --git a/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/StickyVariantProvider.kt b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/StickyVariantProvider.kt new file mode 100644 index 000000000..36eb1c977 --- /dev/null +++ b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/StickyVariantProvider.kt @@ -0,0 +1,48 @@ + + +package com.rishabh.emojipicker + +import android.content.Context +import android.content.Context.MODE_PRIVATE + +/** A class that handles user's emoji variant selection using SharedPreferences. */ +internal class StickyVariantProvider(context: Context) { + companion object { + const val PREFERENCES_FILE_NAME = "androidx.emoji2.emojipicker.preferences" + const val STICKY_VARIANT_PROVIDER_KEY = "pref_key_sticky_variant" + const val KEY_VALUE_DELIMITER = "=" + const val ENTRY_DELIMITER = "|" + } + + private val sharedPreferences = + context.getSharedPreferences(PREFERENCES_FILE_NAME, MODE_PRIVATE) + + private val stickyVariantMap: MutableMap by lazy { + sharedPreferences + .getString(STICKY_VARIANT_PROVIDER_KEY, null) + ?.split(ENTRY_DELIMITER) + ?.associate { entry -> + entry + .split(KEY_VALUE_DELIMITER, limit = 2) + .takeIf { it.size == 2 } + ?.let { it[0] to it[1] } ?: ("" to "") + } + ?.toMutableMap() ?: mutableMapOf() + } + + internal operator fun get(emoji: String): String = stickyVariantMap[emoji] ?: emoji + + internal fun update(baseEmoji: String, variantClicked: String) { + stickyVariantMap.apply { + if (baseEmoji == variantClicked) { + this.remove(baseEmoji) + } else { + this[baseEmoji] = variantClicked + } + sharedPreferences + .edit() + .putString(STICKY_VARIANT_PROVIDER_KEY, entries.joinToString(ENTRY_DELIMITER)) + .commit() + } + } +} diff --git a/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/utils/FileCache.kt b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/utils/FileCache.kt new file mode 100644 index 000000000..0d97b146d --- /dev/null +++ b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/utils/FileCache.kt @@ -0,0 +1,135 @@ + + +package com.rishabh.emojipicker.utils + +import android.content.Context +import android.content.pm.PackageManager +import android.os.Build +import android.util.Log +import androidx.annotation.GuardedBy +import androidx.annotation.RequiresApi +import androidx.annotation.VisibleForTesting +import androidx.core.content.ContextCompat +import com.rishabh.emojipicker.BundledEmojiListLoader +import com.rishabh.emojipicker.EmojiViewItem +import java.io.File +import java.io.IOException + +/** + * A class that manages cache files for the emoji picker. All cache files are stored in DE (Device + * Encryption) storage (N+), and will be invalidated if device OS version or App version is updated. + * + * Currently this class is only used by [BundledEmojiListLoader]. All renderable emojis will be + * cached by categories under /app.package.name/cache/emoji_picker/ + * /emoji.... + */ +internal class FileCache(context: Context) { + + @VisibleForTesting @GuardedBy("lock") internal val emojiPickerCacheDir: File + private val currentProperty: String + private val lock = Any() + + init { + val osVersion = "${Build.VERSION.SDK_INT}_${Build.TIME}" + val appVersion = getVersionCode(context) + currentProperty = "$osVersion.$appVersion" + emojiPickerCacheDir = + File(getDeviceProtectedStorageContext(context).cacheDir, EMOJI_PICKER_FOLDER) + if (!emojiPickerCacheDir.exists()) emojiPickerCacheDir.mkdir() + } + + /** Get cache for a given file name, or write to a new file using the [defaultValue] factory. */ + internal fun getOrPut( + key: String, + defaultValue: () -> List + ): List { + synchronized(lock) { + val targetDir = File(emojiPickerCacheDir, currentProperty) + // No matching cache folder for current property, clear stale cache directory if any + if (!targetDir.exists()) { + emojiPickerCacheDir.listFiles()?.forEach { it.deleteRecursively() } + targetDir.mkdirs() + } + + val targetFile = File(targetDir, key) + return readFrom(targetFile) ?: writeTo(targetFile, defaultValue) + } + } + + private fun readFrom(targetFile: File): List? { + if (!targetFile.isFile) return null + return targetFile + .bufferedReader() + .useLines { it.toList() } + .map { it.split(",") } + .map { EmojiViewItem(it.first(), it.drop(1)) } + } + + private fun writeTo( + targetFile: File, + defaultValue: () -> List + ): List { + val data = defaultValue.invoke() + if (targetFile.exists()) { + if (!targetFile.delete()) { + Log.wtf(TAG, "Can't delete file: $targetFile") + } + } + if (!targetFile.createNewFile()) { + throw IOException("Can't create file: $targetFile") + } + targetFile.bufferedWriter().use { out -> + for (emoji in data) { + out.write(emoji.emoji) + emoji.variants.forEach { out.write(",$it") } + out.newLine() + } + } + return data + } + + /** Returns a new [context] for accessing device protected storage. */ + private fun getDeviceProtectedStorageContext(context: Context) = + context.takeIf { ContextCompat.isDeviceProtectedStorage(it) } + ?: run { ContextCompat.createDeviceProtectedStorageContext(context) } + ?: context + + /** Gets the version code for a package. */ + @Suppress("DEPRECATION") + private fun getVersionCode(context: Context): Long = + try { + if (Build.VERSION.SDK_INT >= 33) Api33Impl.getAppVersionCode(context) + else if (Build.VERSION.SDK_INT >= 28) Api28Impl.getAppVersionCode(context) + else context.packageManager.getPackageInfo(context.packageName, 0).versionCode.toLong() + } catch (e: PackageManager.NameNotFoundException) { + // Default version to 1 + 1 + } + + companion object { + @Volatile private var instance: FileCache? = null + + internal fun getInstance(context: Context): FileCache = + instance ?: synchronized(this) { instance ?: FileCache(context).also { instance = it } } + + private const val EMOJI_PICKER_FOLDER = "emoji_picker" + private const val TAG = "emojipicker.FileCache" + } + + @RequiresApi(Build.VERSION_CODES.TIRAMISU) + internal object Api33Impl { + fun getAppVersionCode(context: Context) = + context.packageManager + .getPackageInfo(context.packageName, PackageManager.PackageInfoFlags.of(0)) + .longVersionCode + } + + @Suppress("DEPRECATION") + @RequiresApi(Build.VERSION_CODES.P) + internal object Api28Impl { + fun getAppVersionCode(context: Context) = + context.packageManager + .getPackageInfo(context.packageName, /* flags= */ 0) + .longVersionCode + } +} diff --git a/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/utils/UnicodeRenderableManager.kt b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/utils/UnicodeRenderableManager.kt new file mode 100644 index 000000000..e2f14df73 --- /dev/null +++ b/emojipicker/app/src/main/java/androidx/emoji2/emojipicker/utils/UnicodeRenderableManager.kt @@ -0,0 +1,69 @@ + + +package com.rishabh.emojipicker.utils + +import android.os.Build +import android.text.TextPaint +import androidx.annotation.VisibleForTesting +import androidx.core.graphics.PaintCompat +import com.rishabh.emojipicker.EmojiPickerView +import androidx.emoji2.text.EmojiCompat + +/** Checks renderability of unicode characters. */ +internal object UnicodeRenderableManager { + + private const val VARIATION_SELECTOR = "\uFE0F" + + private const val YAWNING_FACE_EMOJI = "\uD83E\uDD71" + + private val paint = TextPaint() + + /** + * Some emojis were usual (non-emoji) characters. Old devices cannot render them with variation + * selector (U+FE0F) so it's worth trying to check renderability again without variation + * selector. + */ + private val CATEGORY_MOVED_EMOJIS = + listOf( // These three characters have been emoji since Unicode emoji version 4. + // version 3: https://unicode.org/Public/emoji/3.0/emoji-data.txt + // version 4: https://unicode.org/Public/emoji/4.0/emoji-data.txt + "\u2695\uFE0F", // STAFF OF AESCULAPIUS + "\u2640\uFE0F", // FEMALE SIGN + "\u2642\uFE0F", // MALE SIGN + // These three characters have been emoji since Unicode emoji version 11. + // version 5: https://unicode.org/Public/emoji/5.0/emoji-data.txt + // version 11: https://unicode.org/Public/emoji/11.0/emoji-data.txt + "\u265F\uFE0F", // BLACK_CHESS_PAWN + "\u267E\uFE0F" // PERMANENT_PAPER_SIGN + ) + + /** + * For a given emoji, check it's renderability with EmojiCompat if enabled. Otherwise, use + * [PaintCompat#hasGlyph]. + * + * Note: For older API version, codepoints {@code U+0xFE0F} are removed. + */ + internal fun isEmojiRenderable(emoji: String) = + if (EmojiPickerView.emojiCompatLoaded) + EmojiCompat.get().getEmojiMatch(emoji, Int.MAX_VALUE) == EmojiCompat.EMOJI_SUPPORTED + else getClosestRenderable(emoji) != null + + // Yawning face is added in emoji 12 which is the first version starts to support gender + // inclusive emojis. + internal fun isEmoji12Supported() = isEmojiRenderable(YAWNING_FACE_EMOJI) + + @VisibleForTesting + fun getClosestRenderable(emoji: String): String? { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + return emoji.replace(VARIATION_SELECTOR, "").takeIfHasGlyph() + } + return emoji.takeIfHasGlyph() + ?: run { + if (CATEGORY_MOVED_EMOJIS.contains(emoji)) + emoji.replace(VARIATION_SELECTOR, "").takeIfHasGlyph() + else null + } + } + + private fun String.takeIfHasGlyph() = takeIf { PaintCompat.hasGlyph(paint, this) } +} diff --git a/emojipicker/app/src/main/res/anim/slide_down_and_fade_out.xml b/emojipicker/app/src/main/res/anim/slide_down_and_fade_out.xml new file mode 100644 index 000000000..c25f30ddd --- /dev/null +++ b/emojipicker/app/src/main/res/anim/slide_down_and_fade_out.xml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/emojipicker/app/src/main/res/anim/slide_up_and_fade_in.xml b/emojipicker/app/src/main/res/anim/slide_up_and_fade_in.xml new file mode 100644 index 000000000..618b96e11 --- /dev/null +++ b/emojipicker/app/src/main/res/anim/slide_up_and_fade_in.xml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/emojipicker/app/src/main/res/drawable/couple_heart_men_shadow_skintone.xml b/emojipicker/app/src/main/res/drawable/couple_heart_men_shadow_skintone.xml new file mode 100644 index 000000000..e480cbf52 --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/couple_heart_men_shadow_skintone.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/couple_heart_men_skintone_shadow.xml b/emojipicker/app/src/main/res/drawable/couple_heart_men_skintone_shadow.xml new file mode 100644 index 000000000..6d54233c9 --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/couple_heart_men_skintone_shadow.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/couple_heart_people_shadow_skintone.xml b/emojipicker/app/src/main/res/drawable/couple_heart_people_shadow_skintone.xml new file mode 100644 index 000000000..219fb0aa5 --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/couple_heart_people_shadow_skintone.xml @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/emojipicker/app/src/main/res/drawable/couple_heart_people_skintone_shadow.xml b/emojipicker/app/src/main/res/drawable/couple_heart_people_skintone_shadow.xml new file mode 100644 index 000000000..09e95e563 --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/couple_heart_people_skintone_shadow.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/couple_heart_woman_man_shadow_skintone.xml b/emojipicker/app/src/main/res/drawable/couple_heart_woman_man_shadow_skintone.xml new file mode 100644 index 000000000..1107c60cf --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/couple_heart_woman_man_shadow_skintone.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/couple_heart_woman_man_skintone_shadow.xml b/emojipicker/app/src/main/res/drawable/couple_heart_woman_man_skintone_shadow.xml new file mode 100644 index 000000000..1334b6771 --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/couple_heart_woman_man_skintone_shadow.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/couple_heart_women_shadow_skintone.xml b/emojipicker/app/src/main/res/drawable/couple_heart_women_shadow_skintone.xml new file mode 100644 index 000000000..4fe76d7d1 --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/couple_heart_women_shadow_skintone.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/couple_heart_women_skintone_shadow.xml b/emojipicker/app/src/main/res/drawable/couple_heart_women_skintone_shadow.xml new file mode 100644 index 000000000..b8b660094 --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/couple_heart_women_skintone_shadow.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/gm_filled_emoji_emotions_vd_theme_24.xml b/emojipicker/app/src/main/res/drawable/gm_filled_emoji_emotions_vd_theme_24.xml new file mode 100644 index 000000000..cfdbdab52 --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/gm_filled_emoji_emotions_vd_theme_24.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/emojipicker/app/src/main/res/drawable/gm_filled_emoji_events_vd_theme_24.xml b/emojipicker/app/src/main/res/drawable/gm_filled_emoji_events_vd_theme_24.xml new file mode 100644 index 000000000..f588bf36a --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/gm_filled_emoji_events_vd_theme_24.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/emojipicker/app/src/main/res/drawable/gm_filled_emoji_food_beverage_vd_theme_24.xml b/emojipicker/app/src/main/res/drawable/gm_filled_emoji_food_beverage_vd_theme_24.xml new file mode 100644 index 000000000..989d0fabc --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/gm_filled_emoji_food_beverage_vd_theme_24.xml @@ -0,0 +1,15 @@ + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/gm_filled_emoji_nature_vd_theme_24.xml b/emojipicker/app/src/main/res/drawable/gm_filled_emoji_nature_vd_theme_24.xml new file mode 100644 index 000000000..c259fba2c --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/gm_filled_emoji_nature_vd_theme_24.xml @@ -0,0 +1,15 @@ + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/gm_filled_emoji_objects_vd_theme_24.xml b/emojipicker/app/src/main/res/drawable/gm_filled_emoji_objects_vd_theme_24.xml new file mode 100644 index 000000000..5e028ac9c --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/gm_filled_emoji_objects_vd_theme_24.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/emojipicker/app/src/main/res/drawable/gm_filled_emoji_people_vd_theme_24.xml b/emojipicker/app/src/main/res/drawable/gm_filled_emoji_people_vd_theme_24.xml new file mode 100644 index 000000000..bd647fe4b --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/gm_filled_emoji_people_vd_theme_24.xml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/emojipicker/app/src/main/res/drawable/gm_filled_emoji_symbols_vd_theme_24.xml b/emojipicker/app/src/main/res/drawable/gm_filled_emoji_symbols_vd_theme_24.xml new file mode 100644 index 000000000..571cb545d --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/gm_filled_emoji_symbols_vd_theme_24.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/gm_filled_emoji_transportation_vd_theme_24.xml b/emojipicker/app/src/main/res/drawable/gm_filled_emoji_transportation_vd_theme_24.xml new file mode 100644 index 000000000..99a165e2a --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/gm_filled_emoji_transportation_vd_theme_24.xml @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/gm_filled_flag_vd_theme_24.xml b/emojipicker/app/src/main/res/drawable/gm_filled_flag_vd_theme_24.xml new file mode 100644 index 000000000..f3573b8a2 --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/gm_filled_flag_vd_theme_24.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/emojipicker/app/src/main/res/drawable/handshake_shadow_skintone.xml b/emojipicker/app/src/main/res/drawable/handshake_shadow_skintone.xml new file mode 100644 index 000000000..04259f359 --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/handshake_shadow_skintone.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/handshake_skintone_shadow.xml b/emojipicker/app/src/main/res/drawable/handshake_skintone_shadow.xml new file mode 100644 index 000000000..dfe4f213c --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/handshake_skintone_shadow.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/holding_men_shadow_skintone.xml b/emojipicker/app/src/main/res/drawable/holding_men_shadow_skintone.xml new file mode 100644 index 000000000..4b84e94a6 --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/holding_men_shadow_skintone.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/holding_men_skintone_shadow.xml b/emojipicker/app/src/main/res/drawable/holding_men_skintone_shadow.xml new file mode 100644 index 000000000..e9def1c60 --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/holding_men_skintone_shadow.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/holding_people_shadow_skintone.xml b/emojipicker/app/src/main/res/drawable/holding_people_shadow_skintone.xml new file mode 100644 index 000000000..ebbd0f4cf --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/holding_people_shadow_skintone.xml @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/holding_people_skintone_shadow.xml b/emojipicker/app/src/main/res/drawable/holding_people_skintone_shadow.xml new file mode 100644 index 000000000..039b6207d --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/holding_people_skintone_shadow.xml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/holding_woman_man_shadow_skintone.xml b/emojipicker/app/src/main/res/drawable/holding_woman_man_shadow_skintone.xml new file mode 100644 index 000000000..a921ec264 --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/holding_woman_man_shadow_skintone.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/holding_woman_man_skintone_shadow.xml b/emojipicker/app/src/main/res/drawable/holding_woman_man_skintone_shadow.xml new file mode 100644 index 000000000..85c332764 --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/holding_woman_man_skintone_shadow.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/holding_women_shadow_skintone.xml b/emojipicker/app/src/main/res/drawable/holding_women_shadow_skintone.xml new file mode 100644 index 000000000..0e918b995 --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/holding_women_shadow_skintone.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/holding_women_skintone_shadow.xml b/emojipicker/app/src/main/res/drawable/holding_women_skintone_shadow.xml new file mode 100644 index 000000000..035cc21ea --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/holding_women_skintone_shadow.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/icon_tint_selector.xml b/emojipicker/app/src/main/res/drawable/icon_tint_selector.xml new file mode 100644 index 000000000..50a07511c --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/icon_tint_selector.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/kiss_men_shadow_skintone.xml b/emojipicker/app/src/main/res/drawable/kiss_men_shadow_skintone.xml new file mode 100644 index 000000000..e3df38d56 --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/kiss_men_shadow_skintone.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/kiss_men_skintone_shadow.xml b/emojipicker/app/src/main/res/drawable/kiss_men_skintone_shadow.xml new file mode 100644 index 000000000..2abbd8842 --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/kiss_men_skintone_shadow.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/kiss_people_shadow_skintone.xml b/emojipicker/app/src/main/res/drawable/kiss_people_shadow_skintone.xml new file mode 100644 index 000000000..ddaa48390 --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/kiss_people_shadow_skintone.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/kiss_people_skintone_shadow.xml b/emojipicker/app/src/main/res/drawable/kiss_people_skintone_shadow.xml new file mode 100644 index 000000000..f81d8633d --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/kiss_people_skintone_shadow.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/kiss_woman_man_shadow_skintone.xml b/emojipicker/app/src/main/res/drawable/kiss_woman_man_shadow_skintone.xml new file mode 100644 index 000000000..118312377 --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/kiss_woman_man_shadow_skintone.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/kiss_woman_man_skintone_shadow.xml b/emojipicker/app/src/main/res/drawable/kiss_woman_man_skintone_shadow.xml new file mode 100644 index 000000000..5ded1f960 --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/kiss_woman_man_skintone_shadow.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/kiss_women_shadow_skintone.xml b/emojipicker/app/src/main/res/drawable/kiss_women_shadow_skintone.xml new file mode 100644 index 000000000..555d28cd5 --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/kiss_women_shadow_skintone.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/kiss_women_skintone_shadow.xml b/emojipicker/app/src/main/res/drawable/kiss_women_skintone_shadow.xml new file mode 100644 index 000000000..61d91624b --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/kiss_women_skintone_shadow.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/popup_view_rounded_background.xml b/emojipicker/app/src/main/res/drawable/popup_view_rounded_background.xml new file mode 100644 index 000000000..7ed98b76c --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/popup_view_rounded_background.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/emojipicker/app/src/main/res/drawable/quantum_gm_ic_access_time_filled_vd_theme_24.xml b/emojipicker/app/src/main/res/drawable/quantum_gm_ic_access_time_filled_vd_theme_24.xml new file mode 100644 index 000000000..57e65b17f --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/quantum_gm_ic_access_time_filled_vd_theme_24.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/emojipicker/app/src/main/res/drawable/ripple_emoji_view.xml b/emojipicker/app/src/main/res/drawable/ripple_emoji_view.xml new file mode 100644 index 000000000..9748a72e9 --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/ripple_emoji_view.xml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/emojipicker/app/src/main/res/drawable/ripple_image_view.xml b/emojipicker/app/src/main/res/drawable/ripple_image_view.xml new file mode 100644 index 000000000..4c0c3a46d --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/ripple_image_view.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/drawable/swap_horiz_vd_theme_24.xml b/emojipicker/app/src/main/res/drawable/swap_horiz_vd_theme_24.xml new file mode 100644 index 000000000..e3684d49f --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/swap_horiz_vd_theme_24.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/emojipicker/app/src/main/res/drawable/underline_rounded.xml b/emojipicker/app/src/main/res/drawable/underline_rounded.xml new file mode 100644 index 000000000..6621ad5ab --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/underline_rounded.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/emojipicker/app/src/main/res/drawable/variant_availability_indicator.xml b/emojipicker/app/src/main/res/drawable/variant_availability_indicator.xml new file mode 100644 index 000000000..3df2ec1ef --- /dev/null +++ b/emojipicker/app/src/main/res/drawable/variant_availability_indicator.xml @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/emojipicker/app/src/main/res/layout/category_text_view.xml b/emojipicker/app/src/main/res/layout/category_text_view.xml new file mode 100644 index 000000000..f1f8ac43d --- /dev/null +++ b/emojipicker/app/src/main/res/layout/category_text_view.xml @@ -0,0 +1,21 @@ + + + + + + diff --git a/emojipicker/app/src/main/res/layout/emoji_picker.xml b/emojipicker/app/src/main/res/layout/emoji_picker.xml new file mode 100644 index 000000000..62739a188 --- /dev/null +++ b/emojipicker/app/src/main/res/layout/emoji_picker.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/emojipicker/app/src/main/res/layout/emoji_picker_popup_bidirectional.xml b/emojipicker/app/src/main/res/layout/emoji_picker_popup_bidirectional.xml new file mode 100644 index 000000000..be0c3df79 --- /dev/null +++ b/emojipicker/app/src/main/res/layout/emoji_picker_popup_bidirectional.xml @@ -0,0 +1,26 @@ + + + diff --git a/emojipicker/app/src/main/res/layout/emoji_picker_popup_emoji_view.xml b/emojipicker/app/src/main/res/layout/emoji_picker_popup_emoji_view.xml new file mode 100644 index 000000000..d50dd939b --- /dev/null +++ b/emojipicker/app/src/main/res/layout/emoji_picker_popup_emoji_view.xml @@ -0,0 +1,32 @@ + + + + + + diff --git a/emojipicker/app/src/main/res/layout/emoji_picker_popup_image_view.xml b/emojipicker/app/src/main/res/layout/emoji_picker_popup_image_view.xml new file mode 100644 index 000000000..da10bf120 --- /dev/null +++ b/emojipicker/app/src/main/res/layout/emoji_picker_popup_image_view.xml @@ -0,0 +1,27 @@ + + + + diff --git a/emojipicker/app/src/main/res/layout/empty_category_text_view.xml b/emojipicker/app/src/main/res/layout/empty_category_text_view.xml new file mode 100644 index 000000000..b85ec8fad --- /dev/null +++ b/emojipicker/app/src/main/res/layout/empty_category_text_view.xml @@ -0,0 +1,11 @@ + + + diff --git a/emojipicker/app/src/main/res/layout/header_icon_holder.xml b/emojipicker/app/src/main/res/layout/header_icon_holder.xml new file mode 100644 index 000000000..d878bafa6 --- /dev/null +++ b/emojipicker/app/src/main/res/layout/header_icon_holder.xml @@ -0,0 +1,24 @@ + + + + + + + diff --git a/emojipicker/app/src/main/res/layout/variant_popup.xml b/emojipicker/app/src/main/res/layout/variant_popup.xml new file mode 100644 index 000000000..791a98ba1 --- /dev/null +++ b/emojipicker/app/src/main/res/layout/variant_popup.xml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/emojipicker/app/src/main/res/raw/emoji_category_activity.csv b/emojipicker/app/src/main/res/raw/emoji_category_activity.csv new file mode 100644 index 000000000..ff009b322 --- /dev/null +++ b/emojipicker/app/src/main/res/raw/emoji_category_activity.csv @@ -0,0 +1,115 @@ +🎉 +🎊 +🎈 +🎂 +🎀 +🎁 +🎇 +🎆 +🧨 +🧧 +🪔 +🪅 +🪩 +🎐 +🎏 +🎎 +🎑 +🎍 +🎋 +🎄 +🎃 +🎗️ +🥇 +🥈 +🥉 +🏅 +🎖️ +🏆 +📢 +⚽ +⚾ +🥎 +🏀 +🏐 +🏈 +🏉 +🥅 +🎾 +🏸 +🥍 +🏏 +🏑 +🏒 +🥌 +🛷 +🎿 +⛸️ +🛼 +🩰 +🛹 +⛳ +🎯 +🏹 +🥏 +🪃 +🪁 +🎣 +🤿 +🩱 +🎽 +🥋 +🥊 +🎱 +🏓 +🎳 +♟️ +🪀 +🧩 +🎮 +🕹️ +👾 +🔫 +🎲 +🎰 +🎴 +🀄 +🃏 +🪄 +🎩 +📷 +📸 +🖼️ +🎨 +🖌️ +🖍️ +🪡 +🧵 +🧶 +🎹 +🎷 +🎺 +🎸 +🪕 +🎻 +🪘 +🥁 +🪇 +🪈 +🪗 +🎤 +🎧 +🎚️ +🎛️ +🎙️ +📻 +📺 +📼 +📹 +📽️ +🎥 +🎞️ +🎬 +🎭 +🎫 +🎟️ diff --git a/emojipicker/app/src/main/res/raw/emoji_category_animals_nature.csv b/emojipicker/app/src/main/res/raw/emoji_category_animals_nature.csv new file mode 100644 index 000000000..40a39944a --- /dev/null +++ b/emojipicker/app/src/main/res/raw/emoji_category_animals_nature.csv @@ -0,0 +1,223 @@ +💐 +🌹 +🥀 +🌺 +🌷 +🪷 +🌸 +💮 +🏵️ +🪻 +🌻 +🌼 +🍂 +🍁 +🍄 +🌾 +🌱 +🌿 +🍃 +☘️ +🍀 +🪴 +🌵 +🌴 +🌳 +🌲 +🪵 +🪹 +🪺 +🪨 +⛰️ +🏔️ +❄️ +☃️ +⛄ +🌫️ +🌡️ +🔥 +🌋 +🏜️ +🏞️ +🏝️ +🏖️ +🌅 +🌄 +🌈 +🫧 +🌊 +🌬️ +🌀 +🌪️ +⚡ +☔ +💧 +☁️ +🌨️ +🌧️ +🌩️ +⛈️ +🌦️ +🌥️ +⛅ +🌤️ +☀️ +🌞 +🌝 +🌚 +🌜 +🌛 +⭐ +🌟 +✨ +💫 +🌙 +☄️ +🕳️ +🌠 +🌌 +🌍 +🌎 +🌏 +🪐 +🌑 +🌒 +🌓 +🌔 +🌕 +🌖 +🌗 +🌘 +🙈 +🙉 +🙊 +🐵 +🦁 +🐯 +🐱 +🐶 +🐺 +🐻 +🐻‍❄️ +🐨 +🐼 +🐹 +🐭 +🐰 +🦊 +🦝 +🐮 +🐷 +🐽 +🐗 +🦓 +🦄 +🐴 +🫎 +🐲 +🦎 +🐉 +🦖 +🦕 +🐢 +🐊 +🐍 +🐸 +🐇 +🐁 +🐀 +🐈 +🐈‍⬛ +🐩 +🐕 +🦮 +🐕‍🦺 +🐖 +🐎 +🫏 +🐄 +🐂 +🐃 +🦬 +🐏 +🐑 +🐐 +🦌 +🦙 +🦥 +🦘 +🐘 +🦣 +🦏 +🦛 +🦒 +🐆 +🐅 +🐒 +🦍 +🦧 +🐪 +🐫 +🐿️ +🦫 +🦨 +🦡 +🦔 +🦦 +🦇 +🪽 +🪶 +🐦 +🐦‍⬛ +🐓 +🐔 +🐣 +🐤 +🐥 +🦅 +🦉 +🦜 +🕊️ +🦤 +🦢 +🦆 +🪿 +🦩 +🦚 +🐦‍🔥 +🦃 +🐧 +🦭 +🦈 +🐬 +🐋 +🐳 +🐟 +🐠 +🐡 +🦐 +🦞 +🦀 +🦑 +🐙 +🪼 +🦪 +🪸 +🦂 +🕷️ +🕸️ +🐚 +🐌 +🐜 +🦗 +🪲 +🦟 +🪳 +🪰 +🐝 +🐞 +🦋 +🐛 +🪱 +🦠 +🐾 diff --git a/emojipicker/app/src/main/res/raw/emoji_category_emotions.csv b/emojipicker/app/src/main/res/raw/emoji_category_emotions.csv new file mode 100644 index 000000000..176daa675 --- /dev/null +++ b/emojipicker/app/src/main/res/raw/emoji_category_emotions.csv @@ -0,0 +1,242 @@ +😀 +😃 +😄 +😁 +😆 +😅 +😂 +🤣 +😭 +😉 +😗 +😙 +😚 +😘 +🥰 +😍 +🤩 +🥳 +🫠 +🙃 +🙂 +🥲 +🥹 +😊 +☺️ +😌 +🙂‍↕️ +🙂‍↔️ +😏 +🤤 +😋 +😛 +😝 +😜 +🤪 +🥴 +😔 +🥺 +😬 +😑 +😐 +😶 +😶‍🌫️ +🫥 +🤐 +🫡 +🤔 +🤫 +🫢 +🤭 +🥱 +🤗 +🫣 +😱 +🤨 +🧐 +😒 +🙄 +😮‍💨 +😤 +😠 +😡 +🤬 +😞 +😓 +😟 +😥 +😢 +☹️ +🙁 +🫤 +😕 +😰 +😨 +😧 +😦 +😮 +😯 +😲 +😳 +🤯 +😖 +😣 +😩 +😫 +😵 +😵‍💫 +🫨 +🥶 +🥵 +🤢 +🤮 +😴 +😪 +🤧 +🤒 +🤕 +😷 +🤥 +😇 +🤠 +🤑 +🤓 +😎 +🥸 +🤡 +😈 +👿 +👻 +💀 +☠️ +👹 +👺 +🎃 +💩 +🤖 +👽 +👾 +🌚 +🌝 +🌞 +🌛 +🌜 +🙈 +🙉 +🙊 +😺 +😸 +😹 +😻 +😼 +😽 +🙀 +😿 +😾 +💫 +⭐ +🌟 +✨ +💥 +💨 +💦 +💤 +🕳️ +🔥 +💯 +🎉 +❤️ +🧡 +💛 +💚 +🩵 +💙 +💜 +🤎 +🖤 +🩶 +🤍 +🩷 +💘 +💝 +💖 +💗 +💓 +💞 +💕 +💌 +💟 +♥️ +❣️ +❤️‍🩹 +💔 +❤️‍🔥 +💋 +🫂 +👥 +👤 +🗣️ +👣 +🧠 +🫀 +🫁 +🩸 +🦠 +🦷 +🦴 +👀 +👁️ +👄 +🫦 +👅 +👃,👃,👃🏻,👃🏼,👃🏽,👃🏾,👃🏿 +👂,👂,👂🏻,👂🏼,👂🏽,👂🏾,👂🏿 +🦻,🦻,🦻🏻,🦻🏼,🦻🏽,🦻🏾,🦻🏿 +🦶,🦶,🦶🏻,🦶🏼,🦶🏽,🦶🏾,🦶🏿 +🦵,🦵,🦵🏻,🦵🏼,🦵🏽,🦵🏾,🦵🏿 +🦿 +🦾 +💪,💪,💪🏻,💪🏼,💪🏽,💪🏾,💪🏿 +👏,👏,👏🏻,👏🏼,👏🏽,👏🏾,👏🏿 +👍,👍,👍🏻,👍🏼,👍🏽,👍🏾,👍🏿 +👎,👎,👎🏻,👎🏼,👎🏽,👎🏾,👎🏿 +🫶,🫶,🫶🏻,🫶🏼,🫶🏽,🫶🏾,🫶🏿 +🙌,🙌,🙌🏻,🙌🏼,🙌🏽,🙌🏾,🙌🏿 +👐,👐,👐🏻,👐🏼,👐🏽,👐🏾,👐🏿 +🤲,🤲,🤲🏻,🤲🏼,🤲🏽,🤲🏾,🤲🏿 +🤜,🤜,🤜🏻,🤜🏼,🤜🏽,🤜🏾,🤜🏿 +🤛,🤛,🤛🏻,🤛🏼,🤛🏽,🤛🏾,🤛🏿 +✊,✊,✊🏻,✊🏼,✊🏽,✊🏾,✊🏿 +👊,👊,👊🏻,👊🏼,👊🏽,👊🏾,👊🏿 +🫳,🫳,🫳🏻,🫳🏼,🫳🏽,🫳🏾,🫳🏿 +🫴,🫴,🫴🏻,🫴🏼,🫴🏽,🫴🏾,🫴🏿 +🫱,🫱,🫱🏻,🫱🏼,🫱🏽,🫱🏾,🫱🏿 +🫲,🫲,🫲🏻,🫲🏼,🫲🏽,🫲🏾,🫲🏿 +🫸,🫸,🫸🏻,🫸🏼,🫸🏽,🫸🏾,🫸🏿 +🫷,🫷,🫷🏻,🫷🏼,🫷🏽,🫷🏾,🫷🏿 +👋,👋,👋🏻,👋🏼,👋🏽,👋🏾,👋🏿 +🤚,🤚,🤚🏻,🤚🏼,🤚🏽,🤚🏾,🤚🏿 +🖐️,🖐️,🖐🏻,🖐🏼,🖐🏽,🖐🏾,🖐🏿 +✋,✋,✋🏻,✋🏼,✋🏽,✋🏾,✋🏿 +🖖,🖖,🖖🏻,🖖🏼,🖖🏽,🖖🏾,🖖🏿 +🤟,🤟,🤟🏻,🤟🏼,🤟🏽,🤟🏾,🤟🏿 +🤘,🤘,🤘🏻,🤘🏼,🤘🏽,🤘🏾,🤘🏿 +✌️,✌️,✌🏻,✌🏼,✌🏽,✌🏾,✌🏿 +🤞,🤞,🤞🏻,🤞🏼,🤞🏽,🤞🏾,🤞🏿 +🫰,🫰,🫰🏻,🫰🏼,🫰🏽,🫰🏾,🫰🏿 +🤙,🤙,🤙🏻,🤙🏼,🤙🏽,🤙🏾,🤙🏿 +🤌,🤌,🤌🏻,🤌🏼,🤌🏽,🤌🏾,🤌🏿 +🤏,🤏,🤏🏻,🤏🏼,🤏🏽,🤏🏾,🤏🏿 +👌,👌,👌🏻,👌🏼,👌🏽,👌🏾,👌🏿 +🫵,🫵,🫵🏻,🫵🏼,🫵🏽,🫵🏾,🫵🏿 +👉,👉,👉🏻,👉🏼,👉🏽,👉🏾,👉🏿 +👈,👈,👈🏻,👈🏼,👈🏽,👈🏾,👈🏿 +☝️,☝️,☝🏻,☝🏼,☝🏽,☝🏾,☝🏿 +👆,👆,👆🏻,👆🏼,👆🏽,👆🏾,👆🏿 +👇,👇,👇🏻,👇🏼,👇🏽,👇🏾,👇🏿 +🖕,🖕,🖕🏻,🖕🏼,🖕🏽,🖕🏾,🖕🏿 +✍️,✍️,✍🏻,✍🏼,✍🏽,✍🏾,✍🏿 +🤳,🤳,🤳🏻,🤳🏼,🤳🏽,🤳🏾,🤳🏿 +🙏,🙏,🙏🏻,🙏🏼,🙏🏽,🙏🏾,🙏🏿 +💅,💅,💅🏻,💅🏼,💅🏽,💅🏾,💅🏿 +🤝,🤝,🤝🏻,🫱🏻‍🫲🏼,🫱🏻‍🫲🏽,🫱🏻‍🫲🏾,🫱🏻‍🫲🏿,🫱🏼‍🫲🏻,🤝🏼,🫱🏼‍🫲🏽,🫱🏼‍🫲🏾,🫱🏼‍🫲🏿,🫱🏽‍🫲🏻,🫱🏽‍🫲🏼,🤝🏽,🫱🏽‍🫲🏾,🫱🏽‍🫲🏿,🫱🏾‍🫲🏻,🫱🏾‍🫲🏼,🫱🏾‍🫲🏽,🤝🏾,🫱🏾‍🫲🏿,🫱🏿‍🫲🏻,🫱🏿‍🫲🏼,🫱🏿‍🫲🏽,🫱🏿‍🫲🏾,🤝🏿 diff --git a/emojipicker/app/src/main/res/raw/emoji_category_flags.csv b/emojipicker/app/src/main/res/raw/emoji_category_flags.csv new file mode 100644 index 000000000..c8fd0c064 --- /dev/null +++ b/emojipicker/app/src/main/res/raw/emoji_category_flags.csv @@ -0,0 +1,269 @@ +🏁 +🚩 +🎌 +🏴 +🏳️ +🏳️‍🌈 +🏳️‍⚧️ +🏴‍☠️ +🇦🇨 +🇦🇩 +🇦🇪 +🇦🇫 +🇦🇬 +🇦🇮 +🇦🇱 +🇦🇲 +🇦🇴 +🇦🇶 +🇦🇷 +🇦🇸 +🇦🇹 +🇦🇺 +🇦🇼 +🇦🇽 +🇦🇿 +🇧🇦 +🇧🇧 +🇧🇩 +🇧🇪 +🇧🇫 +🇧🇬 +🇧🇭 +🇧🇮 +🇧🇯 +🇧🇱 +🇧🇲 +🇧🇳 +🇧🇴 +🇧🇶 +🇧🇷 +🇧🇸 +🇧🇹 +🇧🇻 +🇧🇼 +🇧🇾 +🇧🇿 +🇨🇦 +🇨🇨 +🇨🇩 +🇨🇫 +🇨🇬 +🇨🇭 +🇨🇮 +🇨🇰 +🇨🇱 +🇨🇲 +🇨🇳 +🇨🇴 +🇨🇵 +🇨🇷 +🇨🇺 +🇨🇻 +🇨🇼 +🇨🇽 +🇨🇾 +🇨🇿 +🇩🇪 +🇩🇬 +🇩🇯 +🇩🇰 +🇩🇲 +🇩🇴 +🇩🇿 +🇪🇦 +🇪🇨 +🇪🇪 +🇪🇬 +🇪🇭 +🇪🇷 +🇪🇸 +🇪🇹 +🇪🇺 +🇫🇮 +🇫🇯 +🇫🇰 +🇫🇲 +🇫🇴 +🇫🇷 +🇬🇦 +🇬🇧 +🇬🇩 +🇬🇪 +🇬🇫 +🇬🇬 +🇬🇭 +🇬🇮 +🇬🇱 +🇬🇲 +🇬🇳 +🇬🇵 +🇬🇶 +🇬🇷 +🇬🇸 +🇬🇹 +🇬🇺 +🇬🇼 +🇬🇾 +🇭🇰 +🇭🇲 +🇭🇳 +🇭🇷 +🇭🇹 +🇭🇺 +🇮🇨 +🇮🇩 +🇮🇪 +🇮🇱 +🇮🇲 +🇮🇳 +🇮🇴 +🇮🇶 +🇮🇷 +🇮🇸 +🇮🇹 +🇯🇪 +🇯🇲 +🇯🇴 +🇯🇵 +🇰🇪 +🇰🇬 +🇰🇭 +🇰🇮 +🇰🇲 +🇰🇳 +🇰🇵 +🇰🇷 +🇰🇼 +🇰🇾 +🇰🇿 +🇱🇦 +🇱🇧 +🇱🇨 +🇱🇮 +🇱🇰 +🇱🇷 +🇱🇸 +🇱🇹 +🇱🇺 +🇱🇻 +🇱🇾 +🇲🇦 +🇲🇨 +🇲🇩 +🇲🇪 +🇲🇫 +🇲🇬 +🇲🇭 +🇲🇰 +🇲🇱 +🇲🇲 +🇲🇳 +🇲🇴 +🇲🇵 +🇲🇶 +🇲🇷 +🇲🇸 +🇲🇹 +🇲🇺 +🇲🇻 +🇲🇼 +🇲🇽 +🇲🇾 +🇲🇿 +🇳🇦 +🇳🇨 +🇳🇪 +🇳🇫 +🇳🇬 +🇳🇮 +🇳🇱 +🇳🇴 +🇳🇵 +🇳🇷 +🇳🇺 +🇳🇿 +🇴🇲 +🇵🇦 +🇵🇪 +🇵🇫 +🇵🇬 +🇵🇭 +🇵🇰 +🇵🇱 +🇵🇲 +🇵🇳 +🇵🇷 +🇵🇸 +🇵🇹 +🇵🇼 +🇵🇾 +🇶🇦 +🇷🇪 +🇷🇴 +🇷🇸 +🇷🇺 +🇷🇼 +🇸🇦 +🇸🇧 +🇸🇨 +🇸🇩 +🇸🇪 +🇸🇬 +🇸🇭 +🇸🇮 +🇸🇯 +🇸🇰 +🇸🇱 +🇸🇲 +🇸🇳 +🇸🇴 +🇸🇷 +🇸🇸 +🇸🇹 +🇸🇻 +🇸🇽 +🇸🇾 +🇸🇿 +🇹🇦 +🇹🇨 +🇹🇩 +🇹🇫 +🇹🇬 +🇹🇭 +🇹🇯 +🇹🇰 +🇹🇱 +🇹🇲 +🇹🇳 +🇹🇴 +🇹🇷 +🇹🇹 +🇹🇻 +🇹🇼 +🇹🇿 +🇺🇦 +🇺🇬 +🇺🇲 +🇺🇳 +🇺🇸 +🇺🇾 +🇺🇿 +🇻🇦 +🇻🇨 +🇻🇪 +🇻🇬 +🇻🇮 +🇻🇳 +🇻🇺 +🇼🇫 +🇼🇸 +🇽🇰 +🇾🇪 +🇾🇹 +🇿🇦 +🇿🇲 +🇿🇼 +🏴󠁧󠁢󠁥󠁮󠁧󠁿 +🏴󠁧󠁢󠁳󠁣󠁴󠁿 +🏴󠁧󠁢󠁷󠁬󠁳󠁿 diff --git a/emojipicker/app/src/main/res/raw/emoji_category_food_drink.csv b/emojipicker/app/src/main/res/raw/emoji_category_food_drink.csv new file mode 100644 index 000000000..8a15f1e42 --- /dev/null +++ b/emojipicker/app/src/main/res/raw/emoji_category_food_drink.csv @@ -0,0 +1,131 @@ +🍓 +🍒 +🍎 +🍉 +🍑 +🍊 +🥭 +🍍 +🍌 +🍋 +🍋‍🟩 +🍈 +🍏 +🍐 +🥝 +🫒 +🫐 +🍇 +🥥 +🍅 +🌶️ +🫚 +🥕 +🧅 +🌽 +🥦 +🥒 +🥬 +🫛 +🫑 +🥑 +🍠 +🍆 +🧄 +🥔 +🍄‍🟫 +🫘 +🌰 +🥜 +🍞 +🫓 +🥐 +🥖 +🥯 +🧇 +🥞 +🍳 +🥚 +🧀 +🥓 +🥩 +🍗 +🍖 +🍔 +🌭 +🥪 +🥨 +🍟 +🍕 +🫔 +🌮 +🌯 +🥙 +🧆 +🥘 +🍝 +🥫 +🫕 +🥣 +🥗 +🍲 +🍛 +🍜 +🦪 +🦞 +🍣 +🍤 +🥡 +🍚 +🍱 +🥟 +🍢 +🍙 +🍘 +🍥 +🍡 +🥠 +🥮 +🍧 +🍨 +🍦 +🥧 +🍰 +🍮 +🎂 +🧁 +🍭 +🍬 +🍫 +🍩 +🍪 +🍯 +🧂 +🧈 +🍿 +🧊 +🫙 +🥤 +🧋 +🧃 +🥛 +🍼 +🍵 +☕ +🫖 +🧉 +🍺 +🍻 +🥂 +🍾 +🍷 +🥃 +🫗 +🍸 +🍹 +🍶 +🥢 +🍴 +🥄 +🔪 +🍽️ diff --git a/emojipicker/app/src/main/res/raw/emoji_category_objects.csv b/emojipicker/app/src/main/res/raw/emoji_category_objects.csv new file mode 100644 index 000000000..32c4a4fcd --- /dev/null +++ b/emojipicker/app/src/main/res/raw/emoji_category_objects.csv @@ -0,0 +1,265 @@ +📱 +☎️ +📞 +📟 +📠 +🔌 +🔋 +🪫 +🖲️ +💽 +💾 +💿 +📀 +🖥️ +💻 +⌨️ +🖨️ +🖱️ +🪙 +💸 +💵 +💴 +💶 +💷 +💳 +💰 +🧾 +🧮 +⚖️ +🛒 +🛍️ +🕯️ +💡 +🔦 +🏮 +🧱 +🪟 +🪞 +🚪 +🪑 +🛏️ +🛋️ +🚿 +🛁 +🚽 +🧻 +🪠 +🧸 +🪆 +🧷 +🪢 +🧹 +🧴 +🧽 +🧼 +🪥 +🪒 +🪮 +🧺 +🧦 +🧤 +🧣 +👖 +👕 +🎽 +👚 +👔 +👗 +👘 +🥻 +🩱 +👙 +🩳 +🩲 +🧥 +🥼 +🦺 +⛑️ +🪖 +🎓 +🎩 +👒 +🧢 +👑 +🪭 +🎒 +👝 +👛 +👜 +💼 +🧳 +☂️ +🌂 +💍 +💎 +💄 +👠 +👟 +👞 +🥿 +🩴 +👡 +👢 +🥾 +🦯 +🕶️ +👓 +🥽 +⚗️ +🧫 +🧪 +🌡️ +💉 +💊 +🩹 +🩺 +🩻 +🧬 +🔭 +🔬 +📡 +🛰️ +🧯 +🪓 +🪜 +🪣 +🪝 +🧲 +🧰 +🗜️ +🔩 +🪛 +🪚 +🔧 +🔨 +⚒️ +🛠️ +⛏️ +⚙️ +⛓️‍💥 +🔗 +⛓️ +📎 +🖇️ +📏 +📐 +🖌️ +🖍️ +🖊️ +🖋️ +✒️ +✏️ +📝 +📖 +📚 +📒 +📔 +📕 +📓 +📗 +📘 +📙 +🔖 +🗒️ +📄 +📃 +📋 +📑 +📂 +📁 +🗂️ +🗃️ +🗄️ +📊 +📈 +📉 +📇 +🪪 +📌 +📍 +✂️ +🗑️ +📰 +🗞️ +🏷️ +📦 +📫 +📪 +📬 +📭 +📮 +✉️ +📧 +📩 +📨 +💌 +📤 +📥 +🗳️ +🕛 +🕧 +🕐 +🕜 +🕑 +🕝 +🕒 +🕞 +🕓 +🕟 +🕔 +🕠 +🕕 +🕡 +🕖 +🕢 +🕗 +🕣 +🕘 +🕤 +🕙 +🕥 +🕚 +🕦 +⏱️ +⌚ +🕰️ +⌛ +⏳ +⏲️ +⏰ +📅 +📆 +🗓️ +🪧 +🛎️ +🔔 +📯 +📢 +📣 +🔈 +🔉 +🔊 +🔍 +🔎 +🔮 +🧿 +🪬 +📿 +🏺 +⚱️ +⚰️ +🪦 +🚬 +💣 +🪤 +📜 +⚔️ +🗡️ +🛡️ +🗝️ +🔑 +🔐 +🔏 +🔒 +🔓 diff --git a/emojipicker/app/src/main/res/raw/emoji_category_people.csv b/emojipicker/app/src/main/res/raw/emoji_category_people.csv new file mode 100644 index 000000000..f6e06f6a3 --- /dev/null +++ b/emojipicker/app/src/main/res/raw/emoji_category_people.csv @@ -0,0 +1,151 @@ +🙇,🙇‍♀️,🙇🏻‍♀️,🙇🏼‍♀️,🙇🏽‍♀️,🙇🏾‍♀️,🙇🏿‍♀️,🙇‍♂️,🙇🏻‍♂️,🙇🏼‍♂️,🙇🏽‍♂️,🙇🏾‍♂️,🙇🏿‍♂️ +🙋,🙋‍♀️,🙋🏻‍♀️,🙋🏼‍♀️,🙋🏽‍♀️,🙋🏾‍♀️,🙋🏿‍♀️,🙋‍♂️,🙋🏻‍♂️,🙋🏼‍♂️,🙋🏽‍♂️,🙋🏾‍♂️,🙋🏿‍♂️ +💁,💁‍♀️,💁🏻‍♀️,💁🏼‍♀️,💁🏽‍♀️,💁🏾‍♀️,💁🏿‍♀️,💁‍♂️,💁🏻‍♂️,💁🏼‍♂️,💁🏽‍♂️,💁🏾‍♂️,💁🏿‍♂️ +🙆,🙆‍♀️,🙆🏻‍♀️,🙆🏼‍♀️,🙆🏽‍♀️,🙆🏾‍♀️,🙆🏿‍♀️,🙆‍♂️,🙆🏻‍♂️,🙆🏼‍♂️,🙆🏽‍♂️,🙆🏾‍♂️,🙆🏿‍♂️ +🙅,🙅‍♀️,🙅🏻‍♀️,🙅🏼‍♀️,🙅🏽‍♀️,🙅🏾‍♀️,🙅🏿‍♀️,🙅‍♂️,🙅🏻‍♂️,🙅🏼‍♂️,🙅🏽‍♂️,🙅🏾‍♂️,🙅🏿‍♂️ +🤷,🤷‍♀️,🤷🏻‍♀️,🤷🏼‍♀️,🤷🏽‍♀️,🤷🏾‍♀️,🤷🏿‍♀️,🤷‍♂️,🤷🏻‍♂️,🤷🏼‍♂️,🤷🏽‍♂️,🤷🏾‍♂️,🤷🏿‍♂️ +🤦,🤦‍♀️,🤦🏻‍♀️,🤦🏼‍♀️,🤦🏽‍♀️,🤦🏾‍♀️,🤦🏿‍♀️,🤦‍♂️,🤦🏻‍♂️,🤦🏼‍♂️,🤦🏽‍♂️,🤦🏾‍♂️,🤦🏿‍♂️ +🙍,🙍‍♀️,🙍🏻‍♀️,🙍🏼‍♀️,🙍🏽‍♀️,🙍🏾‍♀️,🙍🏿‍♀️,🙍‍♂️,🙍🏻‍♂️,🙍🏼‍♂️,🙍🏽‍♂️,🙍🏾‍♂️,🙍🏿‍♂️ +🙎,🙎‍♀️,🙎🏻‍♀️,🙎🏼‍♀️,🙎🏽‍♀️,🙎🏾‍♀️,🙎🏿‍♀️,🙎‍♂️,🙎🏻‍♂️,🙎🏼‍♂️,🙎🏽‍♂️,🙎🏾‍♂️,🙎🏿‍♂️ +🧏,🧏‍♀️,🧏🏻‍♀️,🧏🏼‍♀️,🧏🏽‍♀️,🧏🏾‍♀️,🧏🏿‍♀️,🧏‍♂️,🧏🏻‍♂️,🧏🏼‍♂️,🧏🏽‍♂️,🧏🏾‍♂️,🧏🏿‍♂️ +💆,💆‍♀️,💆🏻‍♀️,💆🏼‍♀️,💆🏽‍♀️,💆🏾‍♀️,💆🏿‍♀️,💆‍♂️,💆🏻‍♂️,💆🏼‍♂️,💆🏽‍♂️,💆🏾‍♂️,💆🏿‍♂️ +💇,💇‍♀️,💇🏻‍♀️,💇🏼‍♀️,💇🏽‍♀️,💇🏾‍♀️,💇🏿‍♀️,💇‍♂️,💇🏻‍♂️,💇🏼‍♂️,💇🏽‍♂️,💇🏾‍♂️,💇🏿‍♂️ +🧖,🧖‍♀️,🧖🏻‍♀️,🧖🏼‍♀️,🧖🏽‍♀️,🧖🏾‍♀️,🧖🏿‍♀️,🧖‍♂️,🧖🏻‍♂️,🧖🏼‍♂️,🧖🏽‍♂️,🧖🏾‍♂️,🧖🏿‍♂️ +🛀,🛀,🛀🏻,🛀🏼,🛀🏽,🛀🏾,🛀🏿 +🛌,🛌,🛌🏻,🛌🏼,🛌🏽,🛌🏾,🛌🏿 +🧘,🧘‍♀️,🧘🏻‍♀️,🧘🏼‍♀️,🧘🏽‍♀️,🧘🏾‍♀️,🧘🏿‍♀️,🧘‍♂️,🧘🏻‍♂️,🧘🏼‍♂️,🧘🏽‍♂️,🧘🏾‍♂️,🧘🏿‍♂️ +👨‍🦯,👨‍🦯,👨🏻‍🦯,👨🏼‍🦯,👨🏽‍🦯,👨🏾‍🦯,👨🏿‍🦯 +👩‍🦯,👩‍🦯,👩🏻‍🦯,👩🏼‍🦯,👩🏽‍🦯,👩🏾‍🦯,👩🏿‍🦯 +👨‍🦼,👨‍🦼,👨🏻‍🦼,👨🏼‍🦼,👨🏽‍🦼,👨🏾‍🦼,👨🏿‍🦼 +👩‍🦼,👩‍🦼,👩🏻‍🦼,👩🏼‍🦼,👩🏽‍🦼,👩🏾‍🦼,👩🏿‍🦼 +👨‍🦽,👨‍🦽,👨🏻‍🦽,👨🏼‍🦽,👨🏽‍🦽,👨🏾‍🦽,👨🏿‍🦽 +👩‍🦽,👩‍🦽,👩🏻‍🦽,👩🏼‍🦽,👩🏽‍🦽,👩🏾‍🦽,👩🏿‍🦽 +🧎,🧎‍♀️,🧎🏻‍♀️,🧎🏼‍♀️,🧎🏽‍♀️,🧎🏾‍♀️,🧎🏿‍♀️,🧎‍♂️,🧎🏻‍♂️,🧎🏼‍♂️,🧎🏽‍♂️,🧎🏾‍♂️,🧎🏿‍♂️ +🧍,🧍‍♀️,🧍🏻‍♀️,🧍🏼‍♀️,🧍🏽‍♀️,🧍🏾‍♀️,🧍🏿‍♀️,🧍‍♂️,🧍🏻‍♂️,🧍🏼‍♂️,🧍🏽‍♂️,🧍🏾‍♂️,🧍🏿‍♂️ +🚶,🚶‍♀️,🚶🏻‍♀️,🚶🏼‍♀️,🚶🏽‍♀️,🚶🏾‍♀️,🚶🏿‍♀️,🚶‍♂️,🚶🏻‍♂️,🚶🏼‍♂️,🚶🏽‍♂️,🚶🏾‍♂️,🚶🏿‍♂️ +🏃,🏃‍♀️,🏃🏻‍♀️,🏃🏼‍♀️,🏃🏽‍♀️,🏃🏾‍♀️,🏃🏿‍♀️,🏃‍♂️,🏃🏻‍♂️,🏃🏼‍♂️,🏃🏽‍♂️,🏃🏾‍♂️,🏃🏿‍♂️ +🤸,🤸‍♀️,🤸🏻‍♀️,🤸🏼‍♀️,🤸🏽‍♀️,🤸🏾‍♀️,🤸🏿‍♀️,🤸‍♂️,🤸🏻‍♂️,🤸🏼‍♂️,🤸🏽‍♂️,🤸🏾‍♂️,🤸🏿‍♂️ +🏋️,🏋️‍♀️,🏋🏻‍♀️,🏋🏼‍♀️,🏋🏽‍♀️,🏋🏾‍♀️,🏋🏿‍♀️,🏋️‍♂️,🏋🏻‍♂️,🏋🏼‍♂️,🏋🏽‍♂️,🏋🏾‍♂️,🏋🏿‍♂️ +⛹️,⛹️‍♀️,⛹🏻‍♀️,⛹🏼‍♀️,⛹🏽‍♀️,⛹🏾‍♀️,⛹🏿‍♀️,⛹️‍♂️,⛹🏻‍♂️,⛹🏼‍♂️,⛹🏽‍♂️,⛹🏾‍♂️,⛹🏿‍♂️ +🤾,🤾‍♀️,🤾🏻‍♀️,🤾🏼‍♀️,🤾🏽‍♀️,🤾🏾‍♀️,🤾🏿‍♀️,🤾‍♂️,🤾🏻‍♂️,🤾🏼‍♂️,🤾🏽‍♂️,🤾🏾‍♂️,🤾🏿‍♂️ +🚴,🚴‍♀️,🚴🏻‍♀️,🚴🏼‍♀️,🚴🏽‍♀️,🚴🏾‍♀️,🚴🏿‍♀️,🚴‍♂️,🚴🏻‍♂️,🚴🏼‍♂️,🚴🏽‍♂️,🚴🏾‍♂️,🚴🏿‍♂️ +🚵,🚵‍♀️,🚵🏻‍♀️,🚵🏼‍♀️,🚵🏽‍♀️,🚵🏾‍♀️,🚵🏿‍♀️,🚵‍♂️,🚵🏻‍♂️,🚵🏼‍♂️,🚵🏽‍♂️,🚵🏾‍♂️,🚵🏿‍♂️ +🧗,🧗‍♀️,🧗🏻‍♀️,🧗🏼‍♀️,🧗🏽‍♀️,🧗🏾‍♀️,🧗🏿‍♀️,🧗‍♂️,🧗🏻‍♂️,🧗🏼‍♂️,🧗🏽‍♂️,🧗🏾‍♂️,🧗🏿‍♂️ +🤼,🤼‍♀️,🤼‍♂️ +🤹,🤹‍♀️,🤹🏻‍♀️,🤹🏼‍♀️,🤹🏽‍♀️,🤹🏾‍♀️,🤹🏿‍♀️,🤹‍♂️,🤹🏻‍♂️,🤹🏼‍♂️,🤹🏽‍♂️,🤹🏾‍♂️,🤹🏿‍♂️ +🏌️,🏌️‍♀️,🏌🏻‍♀️,🏌🏼‍♀️,🏌🏽‍♀️,🏌🏾‍♀️,🏌🏿‍♀️,🏌️‍♂️,🏌🏻‍♂️,🏌🏼‍♂️,🏌🏽‍♂️,🏌🏾‍♂️,🏌🏿‍♂️ +🏇,🏇,🏇🏻,🏇🏼,🏇🏽,🏇🏾,🏇🏿 +🤺 +⛷️ +🏂,🏂,🏂🏻,🏂🏼,🏂🏽,🏂🏾,🏂🏿 +🪂 +🏄,🏄‍♀️,🏄🏻‍♀️,🏄🏼‍♀️,🏄🏽‍♀️,🏄🏾‍♀️,🏄🏿‍♀️,🏄‍♂️,🏄🏻‍♂️,🏄🏼‍♂️,🏄🏽‍♂️,🏄🏾‍♂️,🏄🏿‍♂️ +🚣,🚣‍♀️,🚣🏻‍♀️,🚣🏼‍♀️,🚣🏽‍♀️,🚣🏾‍♀️,🚣🏿‍♀️,🚣‍♂️,🚣🏻‍♂️,🚣🏼‍♂️,🚣🏽‍♂️,🚣🏾‍♂️,🚣🏿‍♂️ +🏊,🏊‍♀️,🏊🏻‍♀️,🏊🏼‍♀️,🏊🏽‍♀️,🏊🏾‍♀️,🏊🏿‍♀️,🏊‍♂️,🏊🏻‍♂️,🏊🏼‍♂️,🏊🏽‍♂️,🏊🏾‍♂️,🏊🏿‍♂️ +🤽,🤽‍♀️,🤽🏻‍♀️,🤽🏼‍♀️,🤽🏽‍♀️,🤽🏾‍♀️,🤽🏿‍♀️,🤽‍♂️,🤽🏻‍♂️,🤽🏼‍♂️,🤽🏽‍♂️,🤽🏾‍♂️,🤽🏿‍♂️ +🧜,🧜‍♀️,🧜🏻‍♀️,🧜🏼‍♀️,🧜🏽‍♀️,🧜🏾‍♀️,🧜🏿‍♀️,🧜‍♂️,🧜🏻‍♂️,🧜🏼‍♂️,🧜🏽‍♂️,🧜🏾‍♂️,🧜🏿‍♂️ +🧚,🧚‍♀️,🧚🏻‍♀️,🧚🏼‍♀️,🧚🏽‍♀️,🧚🏾‍♀️,🧚🏿‍♀️,🧚‍♂️,🧚🏻‍♂️,🧚🏼‍♂️,🧚🏽‍♂️,🧚🏾‍♂️,🧚🏿‍♂️ +🧞,🧞‍♀️,🧞‍♂️ +🦸,🦸‍♀️,🦸🏻‍♀️,🦸🏼‍♀️,🦸🏽‍♀️,🦸🏾‍♀️,🦸🏿‍♀️,🦸‍♂️,🦸🏻‍♂️,🦸🏼‍♂️,🦸🏽‍♂️,🦸🏾‍♂️,🦸🏿‍♂️ +🦹,🦹‍♀️,🦹🏻‍♀️,🦹🏼‍♀️,🦹🏽‍♀️,🦹🏾‍♀️,🦹🏿‍♀️,🦹‍♂️,🦹🏻‍♂️,🦹🏼‍♂️,🦹🏽‍♂️,🦹🏾‍♂️,🦹🏿‍♂️ +🧝,🧝‍♀️,🧝🏻‍♀️,🧝🏼‍♀️,🧝🏽‍♀️,🧝🏾‍♀️,🧝🏿‍♀️,🧝‍♂️,🧝🏻‍♂️,🧝🏼‍♂️,🧝🏽‍♂️,🧝🏾‍♂️,🧝🏿‍♂️ +🧙,🧙‍♀️,🧙🏻‍♀️,🧙🏼‍♀️,🧙🏽‍♀️,🧙🏾‍♀️,🧙🏿‍♀️,🧙‍♂️,🧙🏻‍♂️,🧙🏼‍♂️,🧙🏽‍♂️,🧙🏾‍♂️,🧙🏿‍♂️ +🧟,🧟‍♀️,🧟‍♂️ +🧛,🧛‍♀️,🧛🏻‍♀️,🧛🏼‍♀️,🧛🏽‍♀️,🧛🏾‍♀️,🧛🏿‍♀️,🧛‍♂️,🧛🏻‍♂️,🧛🏼‍♂️,🧛🏽‍♂️,🧛🏾‍♂️,🧛🏿‍♂️ +👼,👼,👼🏻,👼🏼,👼🏽,👼🏾,👼🏿 +🎅,🎅,🎅🏻,🎅🏼,🎅🏽,🎅🏾,🎅🏿 +🤶,🤶,🤶🏻,🤶🏼,🤶🏽,🤶🏾,🤶🏿 +💂,💂‍♀️,💂🏻‍♀️,💂🏼‍♀️,💂🏽‍♀️,💂🏾‍♀️,💂🏿‍♀️,💂‍♂️,💂🏻‍♂️,💂🏼‍♂️,💂🏽‍♂️,💂🏾‍♂️,💂🏿‍♂️ +🤴,🤴,🤴🏻,🤴🏼,🤴🏽,🤴🏾,🤴🏿 +👸,👸,👸🏻,👸🏼,👸🏽,👸🏾,👸🏿 +🤵,🤵,🤵🏻,🤵🏼,🤵🏽,🤵🏾,🤵🏿 +👰,👰,👰🏻,👰🏼,👰🏽,👰🏾,👰🏿 +👩‍🚀,👨‍🚀,👨🏻‍🚀,👨🏼‍🚀,👨🏽‍🚀,👨🏾‍🚀,👨🏿‍🚀,👩‍🚀,👩🏻‍🚀,👩🏼‍🚀,👩🏽‍🚀,👩🏾‍🚀,👩🏿‍🚀 +👷,👷‍♀️,👷🏻‍♀️,👷🏼‍♀️,👷🏽‍♀️,👷🏾‍♀️,👷🏿‍♀️,👷‍♂️,👷🏻‍♂️,👷🏼‍♂️,👷🏽‍♂️,👷🏾‍♂️,👷🏿‍♂️ +👮,👮‍♀️,👮🏻‍♀️,👮🏼‍♀️,👮🏽‍♀️,👮🏾‍♀️,👮🏿‍♀️,👮‍♂️,👮🏻‍♂️,👮🏼‍♂️,👮🏽‍♂️,👮🏾‍♂️,👮🏿‍♂️ +🕵️,🕵️‍♀️,🕵🏻‍♀️,🕵🏼‍♀️,🕵🏽‍♀️,🕵🏾‍♀️,🕵🏿‍♀️,🕵️‍♂️,🕵🏻‍♂️,🕵🏼‍♂️,🕵🏽‍♂️,🕵🏾‍♂️,🕵🏿‍♂️ +👩‍✈️,👨‍✈️,👨🏻‍✈️,👨🏼‍✈️,👨🏽‍✈️,👨🏾‍✈️,👨🏿‍✈️,👩‍✈️,👩🏻‍✈️,👩🏼‍✈️,👩🏽‍✈️,👩🏾‍✈️,👩🏿‍✈️ +👩‍🔬,👨‍🔬,👨🏻‍🔬,👨🏼‍🔬,👨🏽‍🔬,👨🏾‍🔬,👨🏿‍🔬,👩‍🔬,👩🏻‍🔬,👩🏼‍🔬,👩🏽‍🔬,👩🏾‍🔬,👩🏿‍🔬 +👩‍⚕️,👨‍⚕️,👨🏻‍⚕️,👨🏼‍⚕️,👨🏽‍⚕️,👨🏾‍⚕️,👨🏿‍⚕️,👩‍⚕️,👩🏻‍⚕️,👩🏼‍⚕️,👩🏽‍⚕️,👩🏾‍⚕️,👩🏿‍⚕️ +👩‍🔧,👨‍🔧,👨🏻‍🔧,👨🏼‍🔧,👨🏽‍🔧,👨🏾‍🔧,👨🏿‍🔧,👩‍🔧,👩🏻‍🔧,👩🏼‍🔧,👩🏽‍🔧,👩🏾‍🔧,👩🏿‍🔧 +👩‍🏭,👨‍🏭,👨🏻‍🏭,👨🏼‍🏭,👨🏽‍🏭,👨🏾‍🏭,👨🏿‍🏭,👩‍🏭,👩🏻‍🏭,👩🏼‍🏭,👩🏽‍🏭,👩🏾‍🏭,👩🏿‍🏭 +👩‍🚒,👨‍🚒,👨🏻‍🚒,👨🏼‍🚒,👨🏽‍🚒,👨🏾‍🚒,👨🏿‍🚒,👩‍🚒,👩🏻‍🚒,👩🏼‍🚒,👩🏽‍🚒,👩🏾‍🚒,👩🏿‍🚒 +👩‍🌾,👨‍🌾,👨🏻‍🌾,👨🏼‍🌾,👨🏽‍🌾,👨🏾‍🌾,👨🏿‍🌾,👩‍🌾,👩🏻‍🌾,👩🏼‍🌾,👩🏽‍🌾,👩🏾‍🌾,👩🏿‍🌾 +👩‍🏫,👨‍🏫,👨🏻‍🏫,👨🏼‍🏫,👨🏽‍🏫,👨🏾‍🏫,👨🏿‍🏫,👩‍🏫,👩🏻‍🏫,👩🏼‍🏫,👩🏽‍🏫,👩🏾‍🏫,👩🏿‍🏫 +👩‍🎓,👨‍🎓,👨🏻‍🎓,👨🏼‍🎓,👨🏽‍🎓,👨🏾‍🎓,👨🏿‍🎓,👩‍🎓,👩🏻‍🎓,👩🏼‍🎓,👩🏽‍🎓,👩🏾‍🎓,👩🏿‍🎓 +👩‍💼,👨‍💼,👨🏻‍💼,👨🏼‍💼,👨🏽‍💼,👨🏾‍💼,👨🏿‍💼,👩‍💼,👩🏻‍💼,👩🏼‍💼,👩🏽‍💼,👩🏾‍💼,👩🏿‍💼 +👩‍⚖️,👨‍⚖️,👨🏻‍⚖️,👨🏼‍⚖️,👨🏽‍⚖️,👨🏾‍⚖️,👨🏿‍⚖️,👩‍⚖️,👩🏻‍⚖️,👩🏼‍⚖️,👩🏽‍⚖️,👩🏾‍⚖️,👩🏿‍⚖️ +👩‍💻,👨‍💻,👨🏻‍💻,👨🏼‍💻,👨🏽‍💻,👨🏾‍💻,👨🏿‍💻,👩‍💻,👩🏻‍💻,👩🏼‍💻,👩🏽‍💻,👩🏾‍💻,👩🏿‍💻 +👩‍🎤,👨‍🎤,👨🏻‍🎤,👨🏼‍🎤,👨🏽‍🎤,👨🏾‍🎤,👨🏿‍🎤,👩‍🎤,👩🏻‍🎤,👩🏼‍🎤,👩🏽‍🎤,👩🏾‍🎤,👩🏿‍🎤 +👩‍🎨,👨‍🎨,👨🏻‍🎨,👨🏼‍🎨,👨🏽‍🎨,👨🏾‍🎨,👨🏿‍🎨,👩‍🎨,👩🏻‍🎨,👩🏼‍🎨,👩🏽‍🎨,👩🏾‍🎨,👩🏿‍🎨 +👩‍🍳,👨‍🍳,👨🏻‍🍳,👨🏼‍🍳,👨🏽‍🍳,👨🏾‍🍳,👨🏿‍🍳,👩‍🍳,👩🏻‍🍳,👩🏼‍🍳,👩🏽‍🍳,👩🏾‍🍳,👩🏿‍🍳 +👳,👳‍♀️,👳🏻‍♀️,👳🏼‍♀️,👳🏽‍♀️,👳🏾‍♀️,👳🏿‍♀️,👳‍♂️,👳🏻‍♂️,👳🏼‍♂️,👳🏽‍♂️,👳🏾‍♂️,👳🏿‍♂️ +🧕,🧕,🧕🏻,🧕🏼,🧕🏽,🧕🏾,🧕🏿 +👲,👲,👲🏻,👲🏼,👲🏽,👲🏾,👲🏿 +👶,👶,👶🏻,👶🏼,👶🏽,👶🏾,👶🏿 +🧒,🧒,🧒🏻,🧒🏼,🧒🏽,🧒🏾,🧒🏿 +👦,👦,👦🏻,👦🏼,👦🏽,👦🏾,👦🏿 +👧,👧,👧🏻,👧🏼,👧🏽,👧🏾,👧🏿 +🧑,🧑,🧑🏻,🧑🏼,🧑🏽,🧑🏾,🧑🏿 +👨,👨,👨🏻,👨🏼,👨🏽,👨🏾,👨🏿 +👩,👩,👩🏻,👩🏼,👩🏽,👩🏾,👩🏿 +🧓,🧓,🧓🏻,🧓🏼,🧓🏽,🧓🏾,🧓🏿 +👴,👴,👴🏻,👴🏼,👴🏽,👴🏾,👴🏿 +👵,👵,👵🏻,👵🏼,👵🏽,👵🏾,👵🏿 +👨‍🦳,👨‍🦳,👨🏻‍🦳,👨🏼‍🦳,👨🏽‍🦳,👨🏾‍🦳,👨🏿‍🦳 +👩‍🦳,👩‍🦳,👩🏻‍🦳,👩🏼‍🦳,👩🏽‍🦳,👩🏾‍🦳,👩🏿‍🦳 +👨‍🦰,👨‍🦰,👨🏻‍🦰,👨🏼‍🦰,👨🏽‍🦰,👨🏾‍🦰,👨🏿‍🦰 +👩‍🦰,👩‍🦰,👩🏻‍🦰,👩🏼‍🦰,👩🏽‍🦰,👩🏾‍🦰,👩🏿‍🦰 +👱,👱‍♀️,👱🏻‍♀️,👱🏼‍♀️,👱🏽‍♀️,👱🏾‍♀️,👱🏿‍♀️,👱‍♂️,👱🏻‍♂️,👱🏼‍♂️,👱🏽‍♂️,👱🏾‍♂️,👱🏿‍♂️ +👨‍🦱,👨‍🦱,👨🏻‍🦱,👨🏼‍🦱,👨🏽‍🦱,👨🏾‍🦱,👨🏿‍🦱 +👩‍🦱,👩‍🦱,👩🏻‍🦱,👩🏼‍🦱,👩🏽‍🦱,👩🏾‍🦱,👩🏿‍🦱 +👨‍🦲,👨‍🦲,👨🏻‍🦲,👨🏼‍🦲,👨🏽‍🦲,👨🏾‍🦲,👨🏿‍🦲 +👩‍🦲,👩‍🦲,👩🏻‍🦲,👩🏼‍🦲,👩🏽‍🦲,👩🏾‍🦲,👩🏿‍🦲 +🧔,🧔,🧔🏻,🧔🏼,🧔🏽,🧔🏾,🧔🏿 +🕴️,🕴️,🕴🏻,🕴🏼,🕴🏽,🕴🏾,🕴🏿 +💃,💃,💃🏻,💃🏼,💃🏽,💃🏾,💃🏿 +🕺,🕺,🕺🏻,🕺🏼,🕺🏽,🕺🏾,🕺🏿 +👯,👯‍♀️,👯‍♂️ +👭 +👫 +👬 +💏 +👩‍❤️‍💋‍👨 +👨‍❤️‍💋‍👨 +👩‍❤️‍💋‍👩 +💑 +👩‍❤️‍👨 +👨‍❤️‍👨 +👩‍❤️‍👩 +👪 +👨‍👩‍👦 +👨‍👩‍👧 +👨‍👩‍👧‍👦 +👨‍👩‍👦‍👦 +👨‍👩‍👧‍👧 +👨‍👨‍👦 +👨‍👨‍👧 +👨‍👨‍👧‍👦 +👨‍👨‍👦‍👦 +👨‍👨‍👧‍👧 +👩‍👩‍👦 +👩‍👩‍👧 +👩‍👩‍👧‍👦 +👩‍👩‍👦‍👦 +👩‍👩‍👧‍👧 +👨‍👦 +👨‍👦‍👦 +👨‍👧 +👨‍👧‍👦 +👨‍👧‍👧 +👩‍👦 +👩‍👦‍👦 +👩‍👧 +👩‍👧‍👦 +👩‍👧‍👧 +🤰,🤰,🤰🏻,🤰🏼,🤰🏽,🤰🏾,🤰🏿 +🤱,🤱,🤱🏻,🤱🏼,🤱🏽,🤱🏾,🤱🏿 +🗣️ +👤 +👥 +👣 diff --git a/emojipicker/app/src/main/res/raw/emoji_category_people_gender_inclusive.csv b/emojipicker/app/src/main/res/raw/emoji_category_people_gender_inclusive.csv new file mode 100644 index 000000000..ec86a370b --- /dev/null +++ b/emojipicker/app/src/main/res/raw/emoji_category_people_gender_inclusive.csv @@ -0,0 +1,110 @@ +🙇,🙇,🙇🏻,🙇🏼,🙇🏽,🙇🏾,🙇🏿,🙇‍♀️,🙇🏻‍♀️,🙇🏼‍♀️,🙇🏽‍♀️,🙇🏾‍♀️,🙇🏿‍♀️,🙇‍♂️,🙇🏻‍♂️,🙇🏼‍♂️,🙇🏽‍♂️,🙇🏾‍♂️,🙇🏿‍♂️ +🙋,🙋,🙋🏻,🙋🏼,🙋🏽,🙋🏾,🙋🏿,🙋‍♀️,🙋🏻‍♀️,🙋🏼‍♀️,🙋🏽‍♀️,🙋🏾‍♀️,🙋🏿‍♀️,🙋‍♂️,🙋🏻‍♂️,🙋🏼‍♂️,🙋🏽‍♂️,🙋🏾‍♂️,🙋🏿‍♂️ +💁,💁,💁🏻,💁🏼,💁🏽,💁🏾,💁🏿,💁‍♀️,💁🏻‍♀️,💁🏼‍♀️,💁🏽‍♀️,💁🏾‍♀️,💁🏿‍♀️,💁‍♂️,💁🏻‍♂️,💁🏼‍♂️,💁🏽‍♂️,💁🏾‍♂️,💁🏿‍♂️ +🙆,🙆,🙆🏻,🙆🏼,🙆🏽,🙆🏾,🙆🏿,🙆‍♀️,🙆🏻‍♀️,🙆🏼‍♀️,🙆🏽‍♀️,🙆🏾‍♀️,🙆🏿‍♀️,🙆‍♂️,🙆🏻‍♂️,🙆🏼‍♂️,🙆🏽‍♂️,🙆🏾‍♂️,🙆🏿‍♂️ +🙅,🙅,🙅🏻,🙅🏼,🙅🏽,🙅🏾,🙅🏿,🙅‍♀️,🙅🏻‍♀️,🙅🏼‍♀️,🙅🏽‍♀️,🙅🏾‍♀️,🙅🏿‍♀️,🙅‍♂️,🙅🏻‍♂️,🙅🏼‍♂️,🙅🏽‍♂️,🙅🏾‍♂️,🙅🏿‍♂️ +🤷,🤷,🤷🏻,🤷🏼,🤷🏽,🤷🏾,🤷🏿,🤷‍♀️,🤷🏻‍♀️,🤷🏼‍♀️,🤷🏽‍♀️,🤷🏾‍♀️,🤷🏿‍♀️,🤷‍♂️,🤷🏻‍♂️,🤷🏼‍♂️,🤷🏽‍♂️,🤷🏾‍♂️,🤷🏿‍♂️ +🤦,🤦,🤦🏻,🤦🏼,🤦🏽,🤦🏾,🤦🏿,🤦‍♀️,🤦🏻‍♀️,🤦🏼‍♀️,🤦🏽‍♀️,🤦🏾‍♀️,🤦🏿‍♀️,🤦‍♂️,🤦🏻‍♂️,🤦🏼‍♂️,🤦🏽‍♂️,🤦🏾‍♂️,🤦🏿‍♂️ +🙍,🙍,🙍🏻,🙍🏼,🙍🏽,🙍🏾,🙍🏿,🙍‍♀️,🙍🏻‍♀️,🙍🏼‍♀️,🙍🏽‍♀️,🙍🏾‍♀️,🙍🏿‍♀️,🙍‍♂️,🙍🏻‍♂️,🙍🏼‍♂️,🙍🏽‍♂️,🙍🏾‍♂️,🙍🏿‍♂️ +🙎,🙎,🙎🏻,🙎🏼,🙎🏽,🙎🏾,🙎🏿,🙎‍♀️,🙎🏻‍♀️,🙎🏼‍♀️,🙎🏽‍♀️,🙎🏾‍♀️,🙎🏿‍♀️,🙎‍♂️,🙎🏻‍♂️,🙎🏼‍♂️,🙎🏽‍♂️,🙎🏾‍♂️,🙎🏿‍♂️ +🧏,🧏,🧏🏻,🧏🏼,🧏🏽,🧏🏾,🧏🏿,🧏‍♀️,🧏🏻‍♀️,🧏🏼‍♀️,🧏🏽‍♀️,🧏🏾‍♀️,🧏🏿‍♀️,🧏‍♂️,🧏🏻‍♂️,🧏🏼‍♂️,🧏🏽‍♂️,🧏🏾‍♂️,🧏🏿‍♂️ +💆,💆,💆🏻,💆🏼,💆🏽,💆🏾,💆🏿,💆‍♀️,💆🏻‍♀️,💆🏼‍♀️,💆🏽‍♀️,💆🏾‍♀️,💆🏿‍♀️,💆‍♂️,💆🏻‍♂️,💆🏼‍♂️,💆🏽‍♂️,💆🏾‍♂️,💆🏿‍♂️ +💇,💇,💇🏻,💇🏼,💇🏽,💇🏾,💇🏿,💇‍♀️,💇🏻‍♀️,💇🏼‍♀️,💇🏽‍♀️,💇🏾‍♀️,💇🏿‍♀️,💇‍♂️,💇🏻‍♂️,💇🏼‍♂️,💇🏽‍♂️,💇🏾‍♂️,💇🏿‍♂️ +🧖,🧖,🧖🏻,🧖🏼,🧖🏽,🧖🏾,🧖🏿,🧖‍♀️,🧖🏻‍♀️,🧖🏼‍♀️,🧖🏽‍♀️,🧖🏾‍♀️,🧖🏿‍♀️,🧖‍♂️,🧖🏻‍♂️,🧖🏼‍♂️,🧖🏽‍♂️,🧖🏾‍♂️,🧖🏿‍♂️ +🛀,🛀,🛀🏻,🛀🏼,🛀🏽,🛀🏾,🛀🏿 +🛌,🛌,🛌🏻,🛌🏼,🛌🏽,🛌🏾,🛌🏿 +🧘,🧘,🧘🏻,🧘🏼,🧘🏽,🧘🏾,🧘🏿,🧘‍♀️,🧘🏻‍♀️,🧘🏼‍♀️,🧘🏽‍♀️,🧘🏾‍♀️,🧘🏿‍♀️,🧘‍♂️,🧘🏻‍♂️,🧘🏼‍♂️,🧘🏽‍♂️,🧘🏾‍♂️,🧘🏿‍♂️ +🧍,🧍,🧍🏻,🧍🏼,🧍🏽,🧍🏾,🧍🏿,🧍‍♀️,🧍🏻‍♀️,🧍🏼‍♀️,🧍🏽‍♀️,🧍🏾‍♀️,🧍🏿‍♀️,🧍‍♂️,🧍🏻‍♂️,🧍🏼‍♂️,🧍🏽‍♂️,🧍🏾‍♂️,🧍🏿‍♂️ +🤸,🤸,🤸🏻,🤸🏼,🤸🏽,🤸🏾,🤸🏿,🤸‍♀️,🤸🏻‍♀️,🤸🏼‍♀️,🤸🏽‍♀️,🤸🏾‍♀️,🤸🏿‍♀️,🤸‍♂️,🤸🏻‍♂️,🤸🏼‍♂️,🤸🏽‍♂️,🤸🏾‍♂️,🤸🏿‍♂️ +🧎,🧎,🧎🏻,🧎🏼,🧎🏽,🧎🏾,🧎🏿,🧎‍➡️,🧎🏻‍➡️,🧎🏼‍➡️,🧎🏽‍➡️,🧎🏾‍➡️,🧎🏿‍➡️,🧎‍♀️,🧎🏻‍♀️,🧎🏼‍♀️,🧎🏽‍♀️,🧎🏾‍♀️,🧎🏿‍♀️,🧎‍♀️‍➡️,🧎🏻‍♀️‍➡️,🧎🏼‍♀️‍➡️,🧎🏽‍♀️‍➡️,🧎🏾‍♀️‍➡️,🧎🏿‍♀️‍➡️,🧎‍♂️,🧎🏻‍♂️,🧎🏼‍♂️,🧎🏽‍♂️,🧎🏾‍♂️,🧎🏿‍♂️,🧎‍♂️‍➡️,🧎🏻‍♂️‍➡️,🧎🏼‍♂️‍➡️,🧎🏽‍♂️‍➡️,🧎🏾‍♂️‍➡️,🧎🏿‍♂️‍➡️ +🧑‍🦼,🧑‍🦼,🧑🏻‍🦼,🧑🏼‍🦼,🧑🏽‍🦼,🧑🏾‍🦼,🧑🏿‍🦼,🧑‍🦼‍➡️,🧑🏻‍🦼‍➡️,🧑🏼‍🦼‍➡️,🧑🏽‍🦼‍➡️,🧑🏾‍🦼‍➡️,🧑🏿‍🦼‍➡️,👩‍🦼,👩🏻‍🦼,👩🏼‍🦼,👩🏽‍🦼,👩🏾‍🦼,👩🏿‍🦼,👩‍🦼‍➡️,👩🏻‍🦼‍➡️,👩🏼‍🦼‍➡️,👩🏽‍🦼‍➡️,👩🏾‍🦼‍➡️,👩🏿‍🦼‍➡️,👨‍🦼,👨🏻‍🦼,👨🏼‍🦼,👨🏽‍🦼,👨🏾‍🦼,👨🏿‍🦼,👨‍🦼‍➡️,👨🏻‍🦼‍➡️,👨🏼‍🦼‍➡️,👨🏽‍🦼‍➡️,👨🏾‍🦼‍➡️,👨🏿‍🦼‍➡️ +🧑‍🦽,🧑‍🦽,🧑🏻‍🦽,🧑🏼‍🦽,🧑🏽‍🦽,🧑🏾‍🦽,🧑🏿‍🦽,🧑‍🦽‍➡️,🧑🏻‍🦽‍➡️,🧑🏼‍🦽‍➡️,🧑🏽‍🦽‍➡️,🧑🏾‍🦽‍➡️,🧑🏿‍🦽‍➡️,👩‍🦽,👩🏻‍🦽,👩🏼‍🦽,👩🏽‍🦽,👩🏾‍🦽,👩🏿‍🦽,👩‍🦽‍➡️,👩🏻‍🦽‍➡️,👩🏼‍🦽‍➡️,👩🏽‍🦽‍➡️,👩🏾‍🦽‍➡️,👩🏿‍🦽‍➡️,👨‍🦽,👨🏻‍🦽,👨🏼‍🦽,👨🏽‍🦽,👨🏾‍🦽,👨🏿‍🦽,👨‍🦽‍➡️,👨🏻‍🦽‍➡️,👨🏼‍🦽‍➡️,👨🏽‍🦽‍➡️,👨🏾‍🦽‍➡️,👨🏿‍🦽‍➡️ +🧑‍🦯,🧑‍🦯,🧑🏻‍🦯,🧑🏼‍🦯,🧑🏽‍🦯,🧑🏾‍🦯,🧑🏿‍🦯,🧑‍🦯‍➡️,🧑🏻‍🦯‍➡️,🧑🏼‍🦯‍➡️,🧑🏽‍🦯‍➡️,🧑🏾‍🦯‍➡️,🧑🏿‍🦯‍➡️,👩‍🦯,👩🏻‍🦯,👩🏼‍🦯,👩🏽‍🦯,👩🏾‍🦯,👩🏿‍🦯,👩‍🦯‍➡️,👩🏻‍🦯‍➡️,👩🏼‍🦯‍➡️,👩🏽‍🦯‍➡️,👩🏾‍🦯‍➡️,👩🏿‍🦯‍➡️,👨‍🦯,👨🏻‍🦯,👨🏼‍🦯,👨🏽‍🦯,👨🏾‍🦯,👨🏿‍🦯,👨‍🦯‍➡️,👨🏻‍🦯‍➡️,👨🏼‍🦯‍➡️,👨🏽‍🦯‍➡️,👨🏾‍🦯‍➡️,👨🏿‍🦯‍➡️ +🚶,🚶,🚶🏻,🚶🏼,🚶🏽,🚶🏾,🚶🏿,🚶‍➡️,🚶🏻‍➡️,🚶🏼‍➡️,🚶🏽‍➡️,🚶🏾‍➡️,🚶🏿‍➡️,🚶‍♀️,🚶🏻‍♀️,🚶🏼‍♀️,🚶🏽‍♀️,🚶🏾‍♀️,🚶🏿‍♀️,🚶‍♀️‍➡️,🚶🏻‍♀️‍➡️,🚶🏼‍♀️‍➡️,🚶🏽‍♀️‍➡️,🚶🏾‍♀️‍➡️,🚶🏿‍♀️‍➡️,🚶‍♂️,🚶🏻‍♂️,🚶🏼‍♂️,🚶🏽‍♂️,🚶🏾‍♂️,🚶🏿‍♂️,🚶‍♂️‍➡️,🚶🏻‍♂️‍➡️,🚶🏼‍♂️‍➡️,🚶🏽‍♂️‍➡️,🚶🏾‍♂️‍➡️,🚶🏿‍♂️‍➡️ +🏃,🏃,🏃🏻,🏃🏼,🏃🏽,🏃🏾,🏃🏿,🏃‍➡️,🏃🏻‍➡️,🏃🏼‍➡️,🏃🏽‍➡️,🏃🏾‍➡️,🏃🏿‍➡️,🏃‍♀️,🏃🏻‍♀️,🏃🏼‍♀️,🏃🏽‍♀️,🏃🏾‍♀️,🏃🏿‍♀️,🏃‍♀️‍➡️,🏃🏻‍♀️‍➡️,🏃🏼‍♀️‍➡️,🏃🏽‍♀️‍➡️,🏃🏾‍♀️‍➡️,🏃🏿‍♀️‍➡️,🏃‍♂️,🏃🏻‍♂️,🏃🏼‍♂️,🏃🏽‍♂️,🏃🏾‍♂️,🏃🏿‍♂️,🏃‍♂️‍➡️,🏃🏻‍♂️‍➡️,🏃🏼‍♂️‍➡️,🏃🏽‍♂️‍➡️,🏃🏾‍♂️‍➡️,🏃🏿‍♂️‍➡️ +⛹️,⛹️,⛹🏻,⛹🏼,⛹🏽,⛹🏾,⛹🏿,⛹️‍♀️,⛹🏻‍♀️,⛹🏼‍♀️,⛹🏽‍♀️,⛹🏾‍♀️,⛹🏿‍♀️,⛹️‍♂️,⛹🏻‍♂️,⛹🏼‍♂️,⛹🏽‍♂️,⛹🏾‍♂️,⛹🏿‍♂️ +🤾,🤾,🤾🏻,🤾🏼,🤾🏽,🤾🏾,🤾🏿,🤾‍♀️,🤾🏻‍♀️,🤾🏼‍♀️,🤾🏽‍♀️,🤾🏾‍♀️,🤾🏿‍♀️,🤾‍♂️,🤾🏻‍♂️,🤾🏼‍♂️,🤾🏽‍♂️,🤾🏾‍♂️,🤾🏿‍♂️ +🚴,🚴,🚴🏻,🚴🏼,🚴🏽,🚴🏾,🚴🏿,🚴‍♀️,🚴🏻‍♀️,🚴🏼‍♀️,🚴🏽‍♀️,🚴🏾‍♀️,🚴🏿‍♀️,🚴‍♂️,🚴🏻‍♂️,🚴🏼‍♂️,🚴🏽‍♂️,🚴🏾‍♂️,🚴🏿‍♂️ +🚵,🚵,🚵🏻,🚵🏼,🚵🏽,🚵🏾,🚵🏿,🚵‍♀️,🚵🏻‍♀️,🚵🏼‍♀️,🚵🏽‍♀️,🚵🏾‍♀️,🚵🏿‍♀️,🚵‍♂️,🚵🏻‍♂️,🚵🏼‍♂️,🚵🏽‍♂️,🚵🏾‍♂️,🚵🏿‍♂️ +🧗,🧗,🧗🏻,🧗🏼,🧗🏽,🧗🏾,🧗🏿,🧗‍♀️,🧗🏻‍♀️,🧗🏼‍♀️,🧗🏽‍♀️,🧗🏾‍♀️,🧗🏿‍♀️,🧗‍♂️,🧗🏻‍♂️,🧗🏼‍♂️,🧗🏽‍♂️,🧗🏾‍♂️,🧗🏿‍♂️ +🏋️,🏋️,🏋🏻,🏋🏼,🏋🏽,🏋🏾,🏋🏿,🏋️‍♀️,🏋🏻‍♀️,🏋🏼‍♀️,🏋🏽‍♀️,🏋🏾‍♀️,🏋🏿‍♀️,🏋️‍♂️,🏋🏻‍♂️,🏋🏼‍♂️,🏋🏽‍♂️,🏋🏾‍♂️,🏋🏿‍♂️ +🤼,🤼,🤼‍♀️,🤼‍♂️ +🤹,🤹,🤹🏻,🤹🏼,🤹🏽,🤹🏾,🤹🏿,🤹‍♀️,🤹🏻‍♀️,🤹🏼‍♀️,🤹🏽‍♀️,🤹🏾‍♀️,🤹🏿‍♀️,🤹‍♂️,🤹🏻‍♂️,🤹🏼‍♂️,🤹🏽‍♂️,🤹🏾‍♂️,🤹🏿‍♂️ +🏌️,🏌️,🏌🏻,🏌🏼,🏌🏽,🏌🏾,🏌🏿,🏌️‍♀️,🏌🏻‍♀️,🏌🏼‍♀️,🏌🏽‍♀️,🏌🏾‍♀️,🏌🏿‍♀️,🏌️‍♂️,🏌🏻‍♂️,🏌🏼‍♂️,🏌🏽‍♂️,🏌🏾‍♂️,🏌🏿‍♂️ +🏇,🏇,🏇🏻,🏇🏼,🏇🏽,🏇🏾,🏇🏿 +🤺 +⛷️ +🏂,🏂,🏂🏻,🏂🏼,🏂🏽,🏂🏾,🏂🏿 +🪂 +🏄,🏄,🏄🏻,🏄🏼,🏄🏽,🏄🏾,🏄🏿,🏄‍♀️,🏄🏻‍♀️,🏄🏼‍♀️,🏄🏽‍♀️,🏄🏾‍♀️,🏄🏿‍♀️,🏄‍♂️,🏄🏻‍♂️,🏄🏼‍♂️,🏄🏽‍♂️,🏄🏾‍♂️,🏄🏿‍♂️ +🚣,🚣,🚣🏻,🚣🏼,🚣🏽,🚣🏾,🚣🏿,🚣‍♀️,🚣🏻‍♀️,🚣🏼‍♀️,🚣🏽‍♀️,🚣🏾‍♀️,🚣🏿‍♀️,🚣‍♂️,🚣🏻‍♂️,🚣🏼‍♂️,🚣🏽‍♂️,🚣🏾‍♂️,🚣🏿‍♂️ +🏊,🏊,🏊🏻,🏊🏼,🏊🏽,🏊🏾,🏊🏿,🏊‍♀️,🏊🏻‍♀️,🏊🏼‍♀️,🏊🏽‍♀️,🏊🏾‍♀️,🏊🏿‍♀️,🏊‍♂️,🏊🏻‍♂️,🏊🏼‍♂️,🏊🏽‍♂️,🏊🏾‍♂️,🏊🏿‍♂️ +🤽,🤽,🤽🏻,🤽🏼,🤽🏽,🤽🏾,🤽🏿,🤽‍♀️,🤽🏻‍♀️,🤽🏼‍♀️,🤽🏽‍♀️,🤽🏾‍♀️,🤽🏿‍♀️,🤽‍♂️,🤽🏻‍♂️,🤽🏼‍♂️,🤽🏽‍♂️,🤽🏾‍♂️,🤽🏿‍♂️ +🧜,🧜,🧜🏻,🧜🏼,🧜🏽,🧜🏾,🧜🏿,🧜‍♀️,🧜🏻‍♀️,🧜🏼‍♀️,🧜🏽‍♀️,🧜🏾‍♀️,🧜🏿‍♀️,🧜‍♂️,🧜🏻‍♂️,🧜🏼‍♂️,🧜🏽‍♂️,🧜🏾‍♂️,🧜🏿‍♂️ +🧚,🧚,🧚🏻,🧚🏼,🧚🏽,🧚🏾,🧚🏿,🧚‍♀️,🧚🏻‍♀️,🧚🏼‍♀️,🧚🏽‍♀️,🧚🏾‍♀️,🧚🏿‍♀️,🧚‍♂️,🧚🏻‍♂️,🧚🏼‍♂️,🧚🏽‍♂️,🧚🏾‍♂️,🧚🏿‍♂️ +🧞,🧞,🧞‍♀️,🧞‍♂️ +🧝,🧝,🧝🏻,🧝🏼,🧝🏽,🧝🏾,🧝🏿,🧝‍♀️,🧝🏻‍♀️,🧝🏼‍♀️,🧝🏽‍♀️,🧝🏾‍♀️,🧝🏿‍♀️,🧝‍♂️,🧝🏻‍♂️,🧝🏼‍♂️,🧝🏽‍♂️,🧝🏾‍♂️,🧝🏿‍♂️ +🧙,🧙,🧙🏻,🧙🏼,🧙🏽,🧙🏾,🧙🏿,🧙‍♀️,🧙🏻‍♀️,🧙🏼‍♀️,🧙🏽‍♀️,🧙🏾‍♀️,🧙🏿‍♀️,🧙‍♂️,🧙🏻‍♂️,🧙🏼‍♂️,🧙🏽‍♂️,🧙🏾‍♂️,🧙🏿‍♂️ +🧛,🧛,🧛🏻,🧛🏼,🧛🏽,🧛🏾,🧛🏿,🧛‍♀️,🧛🏻‍♀️,🧛🏼‍♀️,🧛🏽‍♀️,🧛🏾‍♀️,🧛🏿‍♀️,🧛‍♂️,🧛🏻‍♂️,🧛🏼‍♂️,🧛🏽‍♂️,🧛🏾‍♂️,🧛🏿‍♂️ +🧟,🧟,🧟‍♀️,🧟‍♂️ +🧌 +🦸,🦸,🦸🏻,🦸🏼,🦸🏽,🦸🏾,🦸🏿,🦸‍♀️,🦸🏻‍♀️,🦸🏼‍♀️,🦸🏽‍♀️,🦸🏾‍♀️,🦸🏿‍♀️,🦸‍♂️,🦸🏻‍♂️,🦸🏼‍♂️,🦸🏽‍♂️,🦸🏾‍♂️,🦸🏿‍♂️ +🦹,🦹,🦹🏻,🦹🏼,🦹🏽,🦹🏾,🦹🏿,🦹‍♀️,🦹🏻‍♀️,🦹🏼‍♀️,🦹🏽‍♀️,🦹🏾‍♀️,🦹🏿‍♀️,🦹‍♂️,🦹🏻‍♂️,🦹🏼‍♂️,🦹🏽‍♂️,🦹🏾‍♂️,🦹🏿‍♂️ +🥷,🥷,🥷🏻,🥷🏼,🥷🏽,🥷🏾,🥷🏿 +🧑‍🎄,🧑‍🎄,🧑🏻‍🎄,🧑🏼‍🎄,🧑🏽‍🎄,🧑🏾‍🎄,🧑🏿‍🎄,🤶,🤶🏻,🤶🏼,🤶🏽,🤶🏾,🤶🏿,🎅,🎅🏻,🎅🏼,🎅🏽,🎅🏾,🎅🏿 +👼,👼,👼🏻,👼🏼,👼🏽,👼🏾,👼🏿 +💂,💂,💂🏻,💂🏼,💂🏽,💂🏾,💂🏿,💂‍♀️,💂🏻‍♀️,💂🏼‍♀️,💂🏽‍♀️,💂🏾‍♀️,💂🏿‍♀️,💂‍♂️,💂🏻‍♂️,💂🏼‍♂️,💂🏽‍♂️,💂🏾‍♂️,💂🏿‍♂️ +🫅,🫅,🫅🏻,🫅🏼,🫅🏽,🫅🏾,🫅🏿,👸,👸🏻,👸🏼,👸🏽,👸🏾,👸🏿,🤴,🤴🏻,🤴🏼,🤴🏽,🤴🏾,🤴🏿 +🤵,🤵,🤵🏻,🤵🏼,🤵🏽,🤵🏾,🤵🏿,🤵‍♀️,🤵🏻‍♀️,🤵🏼‍♀️,🤵🏽‍♀️,🤵🏾‍♀️,🤵🏿‍♀️,🤵‍♂️,🤵🏻‍♂️,🤵🏼‍♂️,🤵🏽‍♂️,🤵🏾‍♂️,🤵🏿‍♂️ +👰,👰,👰🏻,👰🏼,👰🏽,👰🏾,👰🏿,👰‍♀️,👰🏻‍♀️,👰🏼‍♀️,👰🏽‍♀️,👰🏾‍♀️,👰🏿‍♀️,👰‍♂️,👰🏻‍♂️,👰🏼‍♂️,👰🏽‍♂️,👰🏾‍♂️,👰🏿‍♂️ +🧑‍🚀,🧑‍🚀,🧑🏻‍🚀,🧑🏼‍🚀,🧑🏽‍🚀,🧑🏾‍🚀,🧑🏿‍🚀,👩‍🚀,👩🏻‍🚀,👩🏼‍🚀,👩🏽‍🚀,👩🏾‍🚀,👩🏿‍🚀,👨‍🚀,👨🏻‍🚀,👨🏼‍🚀,👨🏽‍🚀,👨🏾‍🚀,👨🏿‍🚀 +👷,👷,👷🏻,👷🏼,👷🏽,👷🏾,👷🏿,👷‍♀️,👷🏻‍♀️,👷🏼‍♀️,👷🏽‍♀️,👷🏾‍♀️,👷🏿‍♀️,👷‍♂️,👷🏻‍♂️,👷🏼‍♂️,👷🏽‍♂️,👷🏾‍♂️,👷🏿‍♂️ +👮,👮,👮🏻,👮🏼,👮🏽,👮🏾,👮🏿,👮‍♀️,👮🏻‍♀️,👮🏼‍♀️,👮🏽‍♀️,👮🏾‍♀️,👮🏿‍♀️,👮‍♂️,👮🏻‍♂️,👮🏼‍♂️,👮🏽‍♂️,👮🏾‍♂️,👮🏿‍♂️ +🕵️,🕵️,🕵🏻,🕵🏼,🕵🏽,🕵🏾,🕵🏿,🕵️‍♀️,🕵🏻‍♀️,🕵🏼‍♀️,🕵🏽‍♀️,🕵🏾‍♀️,🕵🏿‍♀️,🕵️‍♂️,🕵🏻‍♂️,🕵🏼‍♂️,🕵🏽‍♂️,🕵🏾‍♂️,🕵🏿‍♂️ +🧑‍✈️,🧑‍✈️,🧑🏻‍✈️,🧑🏼‍✈️,🧑🏽‍✈️,🧑🏾‍✈️,🧑🏿‍✈️,👩‍✈️,👩🏻‍✈️,👩🏼‍✈️,👩🏽‍✈️,👩🏾‍✈️,👩🏿‍✈️,👨‍✈️,👨🏻‍✈️,👨🏼‍✈️,👨🏽‍✈️,👨🏾‍✈️,👨🏿‍✈️ +🧑‍🔬,🧑‍🔬,🧑🏻‍🔬,🧑🏼‍🔬,🧑🏽‍🔬,🧑🏾‍🔬,🧑🏿‍🔬,👩‍🔬,👩🏻‍🔬,👩🏼‍🔬,👩🏽‍🔬,👩🏾‍🔬,👩🏿‍🔬,👨‍🔬,👨🏻‍🔬,👨🏼‍🔬,👨🏽‍🔬,👨🏾‍🔬,👨🏿‍🔬 +🧑‍⚕️,🧑‍⚕️,🧑🏻‍⚕️,🧑🏼‍⚕️,🧑🏽‍⚕️,🧑🏾‍⚕️,🧑🏿‍⚕️,👩‍⚕️,👩🏻‍⚕️,👩🏼‍⚕️,👩🏽‍⚕️,👩🏾‍⚕️,👩🏿‍⚕️,👨‍⚕️,👨🏻‍⚕️,👨🏼‍⚕️,👨🏽‍⚕️,👨🏾‍⚕️,👨🏿‍⚕️ +🧑‍🔧,🧑‍🔧,🧑🏻‍🔧,🧑🏼‍🔧,🧑🏽‍🔧,🧑🏾‍🔧,🧑🏿‍🔧,👩‍🔧,👩🏻‍🔧,👩🏼‍🔧,👩🏽‍🔧,👩🏾‍🔧,👩🏿‍🔧,👨‍🔧,👨🏻‍🔧,👨🏼‍🔧,👨🏽‍🔧,👨🏾‍🔧,👨🏿‍🔧 +🧑‍🏭,🧑‍🏭,🧑🏻‍🏭,🧑🏼‍🏭,🧑🏽‍🏭,🧑🏾‍🏭,🧑🏿‍🏭,👩‍🏭,👩🏻‍🏭,👩🏼‍🏭,👩🏽‍🏭,👩🏾‍🏭,👩🏿‍🏭,👨‍🏭,👨🏻‍🏭,👨🏼‍🏭,👨🏽‍🏭,👨🏾‍🏭,👨🏿‍🏭 +🧑‍🚒,🧑‍🚒,🧑🏻‍🚒,🧑🏼‍🚒,🧑🏽‍🚒,🧑🏾‍🚒,🧑🏿‍🚒,👩‍🚒,👩🏻‍🚒,👩🏼‍🚒,👩🏽‍🚒,👩🏾‍🚒,👩🏿‍🚒,👨‍🚒,👨🏻‍🚒,👨🏼‍🚒,👨🏽‍🚒,👨🏾‍🚒,👨🏿‍🚒 +🧑‍🌾,🧑‍🌾,🧑🏻‍🌾,🧑🏼‍🌾,🧑🏽‍🌾,🧑🏾‍🌾,🧑🏿‍🌾,👩‍🌾,👩🏻‍🌾,👩🏼‍🌾,👩🏽‍🌾,👩🏾‍🌾,👩🏿‍🌾,👨‍🌾,👨🏻‍🌾,👨🏼‍🌾,👨🏽‍🌾,👨🏾‍🌾,👨🏿‍🌾 +🧑‍🏫,🧑‍🏫,🧑🏻‍🏫,🧑🏼‍🏫,🧑🏽‍🏫,🧑🏾‍🏫,🧑🏿‍🏫,👩‍🏫,👩🏻‍🏫,👩🏼‍🏫,👩🏽‍🏫,👩🏾‍🏫,👩🏿‍🏫,👨‍🏫,👨🏻‍🏫,👨🏼‍🏫,👨🏽‍🏫,👨🏾‍🏫,👨🏿‍🏫 +🧑‍🎓,🧑‍🎓,🧑🏻‍🎓,🧑🏼‍🎓,🧑🏽‍🎓,🧑🏾‍🎓,🧑🏿‍🎓,👩‍🎓,👩🏻‍🎓,👩🏼‍🎓,👩🏽‍🎓,👩🏾‍🎓,👩🏿‍🎓,👨‍🎓,👨🏻‍🎓,👨🏼‍🎓,👨🏽‍🎓,👨🏾‍🎓,👨🏿‍🎓 +🧑‍💼,🧑‍💼,🧑🏻‍💼,🧑🏼‍💼,🧑🏽‍💼,🧑🏾‍💼,🧑🏿‍💼,👩‍💼,👩🏻‍💼,👩🏼‍💼,👩🏽‍💼,👩🏾‍💼,👩🏿‍💼,👨‍💼,👨🏻‍💼,👨🏼‍💼,👨🏽‍💼,👨🏾‍💼,👨🏿‍💼 +🧑‍⚖️,🧑‍⚖️,🧑🏻‍⚖️,🧑🏼‍⚖️,🧑🏽‍⚖️,🧑🏾‍⚖️,🧑🏿‍⚖️,👩‍⚖️,👩🏻‍⚖️,👩🏼‍⚖️,👩🏽‍⚖️,👩🏾‍⚖️,👩🏿‍⚖️,👨‍⚖️,👨🏻‍⚖️,👨🏼‍⚖️,👨🏽‍⚖️,👨🏾‍⚖️,👨🏿‍⚖️ +🧑‍💻,🧑‍💻,🧑🏻‍💻,🧑🏼‍💻,🧑🏽‍💻,🧑🏾‍💻,🧑🏿‍💻,👩‍💻,👩🏻‍💻,👩🏼‍💻,👩🏽‍💻,👩🏾‍💻,👩🏿‍💻,👨‍💻,👨🏻‍💻,👨🏼‍💻,👨🏽‍💻,👨🏾‍💻,👨🏿‍💻 +🧑‍🎤,🧑‍🎤,🧑🏻‍🎤,🧑🏼‍🎤,🧑🏽‍🎤,🧑🏾‍🎤,🧑🏿‍🎤,👩‍🎤,👩🏻‍🎤,👩🏼‍🎤,👩🏽‍🎤,👩🏾‍🎤,👩🏿‍🎤,👨‍🎤,👨🏻‍🎤,👨🏼‍🎤,👨🏽‍🎤,👨🏾‍🎤,👨🏿‍🎤 +🧑‍🎨,🧑‍🎨,🧑🏻‍🎨,🧑🏼‍🎨,🧑🏽‍🎨,🧑🏾‍🎨,🧑🏿‍🎨,👩‍🎨,👩🏻‍🎨,👩🏼‍🎨,👩🏽‍🎨,👩🏾‍🎨,👩🏿‍🎨,👨‍🎨,👨🏻‍🎨,👨🏼‍🎨,👨🏽‍🎨,👨🏾‍🎨,👨🏿‍🎨 +🧑‍🍳,🧑‍🍳,🧑🏻‍🍳,🧑🏼‍🍳,🧑🏽‍🍳,🧑🏾‍🍳,🧑🏿‍🍳,👩‍🍳,👩🏻‍🍳,👩🏼‍🍳,👩🏽‍🍳,👩🏾‍🍳,👩🏿‍🍳,👨‍🍳,👨🏻‍🍳,👨🏼‍🍳,👨🏽‍🍳,👨🏾‍🍳,👨🏿‍🍳 +👳,👳,👳🏻,👳🏼,👳🏽,👳🏾,👳🏿,👳‍♀️,👳🏻‍♀️,👳🏼‍♀️,👳🏽‍♀️,👳🏾‍♀️,👳🏿‍♀️,👳‍♂️,👳🏻‍♂️,👳🏼‍♂️,👳🏽‍♂️,👳🏾‍♂️,👳🏿‍♂️ +🧕,🧕,🧕🏻,🧕🏼,🧕🏽,🧕🏾,🧕🏿 +👲,👲,👲🏻,👲🏼,👲🏽,👲🏾,👲🏿 +👶,👶,👶🏻,👶🏼,👶🏽,👶🏾,👶🏿 +🧒,🧒,🧒🏻,🧒🏼,🧒🏽,🧒🏾,🧒🏿,👧,👧🏻,👧🏼,👧🏽,👧🏾,👧🏿,👦,👦🏻,👦🏼,👦🏽,👦🏾,👦🏿 +🧑,🧑,🧑🏻,🧑🏼,🧑🏽,🧑🏾,🧑🏿,👩,👩🏻,👩🏼,👩🏽,👩🏾,👩🏿,👨,👨🏻,👨🏼,👨🏽,👨🏾,👨🏿 +🧓,🧓,🧓🏻,🧓🏼,🧓🏽,🧓🏾,🧓🏿,👵,👵🏻,👵🏼,👵🏽,👵🏾,👵🏿,👴,👴🏻,👴🏼,👴🏽,👴🏾,👴🏿 +🧑‍🦳,🧑‍🦳,🧑🏻‍🦳,🧑🏼‍🦳,🧑🏽‍🦳,🧑🏾‍🦳,🧑🏿‍🦳,👩‍🦳,👩🏻‍🦳,👩🏼‍🦳,👩🏽‍🦳,👩🏾‍🦳,👩🏿‍🦳,👨‍🦳,👨🏻‍🦳,👨🏼‍🦳,👨🏽‍🦳,👨🏾‍🦳,👨🏿‍🦳 +🧑‍🦰,🧑‍🦰,🧑🏻‍🦰,🧑🏼‍🦰,🧑🏽‍🦰,🧑🏾‍🦰,🧑🏿‍🦰,👩‍🦰,👩🏻‍🦰,👩🏼‍🦰,👩🏽‍🦰,👩🏾‍🦰,👩🏿‍🦰,👨‍🦰,👨🏻‍🦰,👨🏼‍🦰,👨🏽‍🦰,👨🏾‍🦰,👨🏿‍🦰 +👱,👱,👱🏻,👱🏼,👱🏽,👱🏾,👱🏿,👱‍♀️,👱🏻‍♀️,👱🏼‍♀️,👱🏽‍♀️,👱🏾‍♀️,👱🏿‍♀️,👱‍♂️,👱🏻‍♂️,👱🏼‍♂️,👱🏽‍♂️,👱🏾‍♂️,👱🏿‍♂️ +🧑‍🦱,🧑‍🦱,🧑🏻‍🦱,🧑🏼‍🦱,🧑🏽‍🦱,🧑🏾‍🦱,🧑🏿‍🦱,👩‍🦱,👩🏻‍🦱,👩🏼‍🦱,👩🏽‍🦱,👩🏾‍🦱,👩🏿‍🦱,👨‍🦱,👨🏻‍🦱,👨🏼‍🦱,👨🏽‍🦱,👨🏾‍🦱,👨🏿‍🦱 +🧑‍🦲,🧑‍🦲,🧑🏻‍🦲,🧑🏼‍🦲,🧑🏽‍🦲,🧑🏾‍🦲,🧑🏿‍🦲,👩‍🦲,👩🏻‍🦲,👩🏼‍🦲,👩🏽‍🦲,👩🏾‍🦲,👩🏿‍🦲,👨‍🦲,👨🏻‍🦲,👨🏼‍🦲,👨🏽‍🦲,👨🏾‍🦲,👨🏿‍🦲 +🧔,🧔,🧔🏻,🧔🏼,🧔🏽,🧔🏾,🧔🏿,🧔‍♀️,🧔🏻‍♀️,🧔🏼‍♀️,🧔🏽‍♀️,🧔🏾‍♀️,🧔🏿‍♀️,🧔‍♂️,🧔🏻‍♂️,🧔🏼‍♂️,🧔🏽‍♂️,🧔🏾‍♂️,🧔🏿‍♂️ +🕴️,🕴️,🕴🏻,🕴🏼,🕴🏽,🕴🏾,🕴🏿 +💃,💃,💃🏻,💃🏼,💃🏽,💃🏾,💃🏿 +🕺,🕺,🕺🏻,🕺🏼,🕺🏽,🕺🏾,🕺🏿 +👯,👯,👯‍♂️,👯‍♀️ +🧑‍🤝‍🧑,🧑‍🤝‍🧑,🧑🏻‍🤝‍🧑🏻,🧑🏻‍🤝‍🧑🏼,🧑🏻‍🤝‍🧑🏽,🧑🏻‍🤝‍🧑🏾,🧑🏻‍🤝‍🧑🏿,🧑🏼‍🤝‍🧑🏻,🧑🏼‍🤝‍🧑🏼,🧑🏼‍🤝‍🧑🏽,🧑🏼‍🤝‍🧑🏾,🧑🏼‍🤝‍🧑🏿,🧑🏽‍🤝‍🧑🏻,🧑🏽‍🤝‍🧑🏼,🧑🏽‍🤝‍🧑🏽,🧑🏽‍🤝‍🧑🏾,🧑🏽‍🤝‍🧑🏿,🧑🏾‍🤝‍🧑🏻,🧑🏾‍🤝‍🧑🏼,🧑🏾‍🤝‍🧑🏽,🧑🏾‍🤝‍🧑🏾,🧑🏾‍🤝‍🧑🏿,🧑🏿‍🤝‍🧑🏻,🧑🏿‍🤝‍🧑🏼,🧑🏿‍🤝‍🧑🏽,🧑🏿‍🤝‍🧑🏾,🧑🏿‍🤝‍🧑🏿 +👭,👭,👭🏻,👩🏻‍🤝‍👩🏼,👩🏻‍🤝‍👩🏽,👩🏻‍🤝‍👩🏾,👩🏻‍🤝‍👩🏿,👩🏼‍🤝‍👩🏻,👭🏼,👩🏼‍🤝‍👩🏽,👩🏼‍🤝‍👩🏾,👩🏼‍🤝‍👩🏿,👩🏽‍🤝‍👩🏻,👩🏽‍🤝‍👩🏼,👭🏽,👩🏽‍🤝‍👩🏾,👩🏽‍🤝‍👩🏿,👩🏾‍🤝‍👩🏻,👩🏾‍🤝‍👩🏼,👩🏾‍🤝‍👩🏽,👭🏾,👩🏾‍🤝‍👩🏿,👩🏿‍🤝‍👩🏻,👩🏿‍🤝‍👩🏼,👩🏿‍🤝‍👩🏽,👩🏿‍🤝‍👩🏾,👭🏿 +👬,👬,👬🏻,👨🏻‍🤝‍👨🏼,👨🏻‍🤝‍👨🏽,👨🏻‍🤝‍👨🏾,👨🏻‍🤝‍👨🏿,👨🏼‍🤝‍👨🏻,👬🏼,👨🏼‍🤝‍👨🏽,👨🏼‍🤝‍👨🏾,👨🏼‍🤝‍👨🏿,👨🏽‍🤝‍👨🏻,👨🏽‍🤝‍👨🏼,👬🏽,👨🏽‍🤝‍👨🏾,👨🏽‍🤝‍👨🏿,👨🏾‍🤝‍👨🏻,👨🏾‍🤝‍👨🏼,👨🏾‍🤝‍👨🏽,👬🏾,👨🏾‍🤝‍👨🏿,👨🏿‍🤝‍👨🏻,👨🏿‍🤝‍👨🏼,👨🏿‍🤝‍👨🏽,👨🏿‍🤝‍👨🏾,👬🏿 +👫,👫,👫🏻,👩🏻‍🤝‍👨🏼,👩🏻‍🤝‍👨🏽,👩🏻‍🤝‍👨🏾,👩🏻‍🤝‍👨🏿,👩🏼‍🤝‍👨🏻,👫🏼,👩🏼‍🤝‍👨🏽,👩🏼‍🤝‍👨🏾,👩🏼‍🤝‍👨🏿,👩🏽‍🤝‍👨🏻,👩🏽‍🤝‍👨🏼,👫🏽,👩🏽‍🤝‍👨🏾,👩🏽‍🤝‍👨🏿,👩🏾‍🤝‍👨🏻,👩🏾‍🤝‍👨🏼,👩🏾‍🤝‍👨🏽,👫🏾,👩🏾‍🤝‍👨🏿,👩🏿‍🤝‍👨🏻,👩🏿‍🤝‍👨🏼,👩🏿‍🤝‍👨🏽,👩🏿‍🤝‍👨🏾,👫🏿 +💏,💏,💏🏻,🧑🏻‍❤️‍💋‍🧑🏼,🧑🏻‍❤️‍💋‍🧑🏽,🧑🏻‍❤️‍💋‍🧑🏾,🧑🏻‍❤️‍💋‍🧑🏿,🧑🏼‍❤️‍💋‍🧑🏻,💏🏼,🧑🏼‍❤️‍💋‍🧑🏽,🧑🏼‍❤️‍💋‍🧑🏾,🧑🏼‍❤️‍💋‍🧑🏿,🧑🏽‍❤️‍💋‍🧑🏻,🧑🏽‍❤️‍💋‍🧑🏼,💏🏽,🧑🏽‍❤️‍💋‍🧑🏾,🧑🏽‍❤️‍💋‍🧑🏿,🧑🏾‍❤️‍💋‍🧑🏻,🧑🏾‍❤️‍💋‍🧑🏼,🧑🏾‍❤️‍💋‍🧑🏽,💏🏾,🧑🏾‍❤️‍💋‍🧑🏿,🧑🏿‍❤️‍💋‍🧑🏻,🧑🏿‍❤️‍💋‍🧑🏼,🧑🏿‍❤️‍💋‍🧑🏽,🧑🏿‍❤️‍💋‍🧑🏾,💏🏿 +👩‍❤️‍💋‍👨,👩‍❤️‍💋‍👨,👩🏻‍❤️‍💋‍👨🏻,👩🏻‍❤️‍💋‍👨🏼,👩🏻‍❤️‍💋‍👨🏽,👩🏻‍❤️‍💋‍👨🏾,👩🏻‍❤️‍💋‍👨🏿,👩🏼‍❤️‍💋‍👨🏻,👩🏼‍❤️‍💋‍👨🏼,👩🏼‍❤️‍💋‍👨🏽,👩🏼‍❤️‍💋‍👨🏾,👩🏼‍❤️‍💋‍👨🏿,👩🏽‍❤️‍💋‍👨🏻,👩🏽‍❤️‍💋‍👨🏼,👩🏽‍❤️‍💋‍👨🏽,👩🏽‍❤️‍💋‍👨🏾,👩🏽‍❤️‍💋‍👨🏿,👩🏾‍❤️‍💋‍👨🏻,👩🏾‍❤️‍💋‍👨🏼,👩🏾‍❤️‍💋‍👨🏽,👩🏾‍❤️‍💋‍👨🏾,👩🏾‍❤️‍💋‍👨🏿,👩🏿‍❤️‍💋‍👨🏻,👩🏿‍❤️‍💋‍👨🏼,👩🏿‍❤️‍💋‍👨🏽,👩🏿‍❤️‍💋‍👨🏾,👩🏿‍❤️‍💋‍👨🏿 +👨‍❤️‍💋‍👨,👨‍❤️‍💋‍👨,👨🏻‍❤️‍💋‍👨🏻,👨🏻‍❤️‍💋‍👨🏼,👨🏻‍❤️‍💋‍👨🏽,👨🏻‍❤️‍💋‍👨🏾,👨🏻‍❤️‍💋‍👨🏿,👨🏼‍❤️‍💋‍👨🏻,👨🏼‍❤️‍💋‍👨🏼,👨🏼‍❤️‍💋‍👨🏽,👨🏼‍❤️‍💋‍👨🏾,👨🏼‍❤️‍💋‍👨🏿,👨🏽‍❤️‍💋‍👨🏻,👨🏽‍❤️‍💋‍👨🏼,👨🏽‍❤️‍💋‍👨🏽,👨🏽‍❤️‍💋‍👨🏾,👨🏽‍❤️‍💋‍👨🏿,👨🏾‍❤️‍💋‍👨🏻,👨🏾‍❤️‍💋‍👨🏼,👨🏾‍❤️‍💋‍👨🏽,👨🏾‍❤️‍💋‍👨🏾,👨🏾‍❤️‍💋‍👨🏿,👨🏿‍❤️‍💋‍👨🏻,👨🏿‍❤️‍💋‍👨🏼,👨🏿‍❤️‍💋‍👨🏽,👨🏿‍❤️‍💋‍👨🏾,👨🏿‍❤️‍💋‍👨🏿 +👩‍❤️‍💋‍👩,👩‍❤️‍💋‍👩,👩🏻‍❤️‍💋‍👩🏻,👩🏻‍❤️‍💋‍👩🏼,👩🏻‍❤️‍💋‍👩🏽,👩🏻‍❤️‍💋‍👩🏾,👩🏻‍❤️‍💋‍👩🏿,👩🏼‍❤️‍💋‍👩🏻,👩🏼‍❤️‍💋‍👩🏼,👩🏼‍❤️‍💋‍👩🏽,👩🏼‍❤️‍💋‍👩🏾,👩🏼‍❤️‍💋‍👩🏿,👩🏽‍❤️‍💋‍👩🏻,👩🏽‍❤️‍💋‍👩🏼,👩🏽‍❤️‍💋‍👩🏽,👩🏽‍❤️‍💋‍👩🏾,👩🏽‍❤️‍💋‍👩🏿,👩🏾‍❤️‍💋‍👩🏻,👩🏾‍❤️‍💋‍👩🏼,👩🏾‍❤️‍💋‍👩🏽,👩🏾‍❤️‍💋‍👩🏾,👩🏾‍❤️‍💋‍👩🏿,👩🏿‍❤️‍💋‍👩🏻,👩🏿‍❤️‍💋‍👩🏼,👩🏿‍❤️‍💋‍👩🏽,👩🏿‍❤️‍💋‍👩🏾,👩🏿‍❤️‍💋‍👩🏿 +💑,💑,💑🏻,🧑🏻‍❤️‍🧑🏼,🧑🏻‍❤️‍🧑🏽,🧑🏻‍❤️‍🧑🏾,🧑🏻‍❤️‍🧑🏿,🧑🏼‍❤️‍🧑🏻,💑🏼,🧑🏼‍❤️‍🧑🏽,🧑🏼‍❤️‍🧑🏾,🧑🏼‍❤️‍🧑🏿,🧑🏽‍❤️‍🧑🏻,🧑🏽‍❤️‍🧑🏼,💑🏽,🧑🏽‍❤️‍🧑🏾,🧑🏽‍❤️‍🧑🏿,🧑🏾‍❤️‍🧑🏻,🧑🏾‍❤️‍🧑🏼,🧑🏾‍❤️‍🧑🏽,💑🏾,🧑🏾‍❤️‍🧑🏿,🧑🏿‍❤️‍🧑🏻,🧑🏿‍❤️‍🧑🏼,🧑🏿‍❤️‍🧑🏽,🧑🏿‍❤️‍🧑🏾,💑🏿 +👩‍❤️‍👨,👩‍❤️‍👨,👩🏻‍❤️‍👨🏻,👩🏻‍❤️‍👨🏼,👩🏻‍❤️‍👨🏽,👩🏻‍❤️‍👨🏾,👩🏻‍❤️‍👨🏿,👩🏼‍❤️‍👨🏻,👩🏼‍❤️‍👨🏼,👩🏼‍❤️‍👨🏽,👩🏼‍❤️‍👨🏾,👩🏼‍❤️‍👨🏿,👩🏽‍❤️‍👨🏻,👩🏽‍❤️‍👨🏼,👩🏽‍❤️‍👨🏽,👩🏽‍❤️‍👨🏾,👩🏽‍❤️‍👨🏿,👩🏾‍❤️‍👨🏻,👩🏾‍❤️‍👨🏼,👩🏾‍❤️‍👨🏽,👩🏾‍❤️‍👨🏾,👩🏾‍❤️‍👨🏿,👩🏿‍❤️‍👨🏻,👩🏿‍❤️‍👨🏼,👩🏿‍❤️‍👨🏽,👩🏿‍❤️‍👨🏾,👩🏿‍❤️‍👨🏿 +👨‍❤️‍👨,👨‍❤️‍👨,👨🏻‍❤️‍👨🏻,👨🏻‍❤️‍👨🏼,👨🏻‍❤️‍👨🏽,👨🏻‍❤️‍👨🏾,👨🏻‍❤️‍👨🏿,👨🏼‍❤️‍👨🏻,👨🏼‍❤️‍👨🏼,👨🏼‍❤️‍👨🏽,👨🏼‍❤️‍👨🏾,👨🏼‍❤️‍👨🏿,👨🏽‍❤️‍👨🏻,👨🏽‍❤️‍👨🏼,👨🏽‍❤️‍👨🏽,👨🏽‍❤️‍👨🏾,👨🏽‍❤️‍👨🏿,👨🏾‍❤️‍👨🏻,👨🏾‍❤️‍👨🏼,👨🏾‍❤️‍👨🏽,👨🏾‍❤️‍👨🏾,👨🏾‍❤️‍👨🏿,👨🏿‍❤️‍👨🏻,👨🏿‍❤️‍👨🏼,👨🏿‍❤️‍👨🏽,👨🏿‍❤️‍👨🏾,👨🏿‍❤️‍👨🏿 +👩‍❤️‍👩,👩‍❤️‍👩,👩🏻‍❤️‍👩🏻,👩🏻‍❤️‍👩🏼,👩🏻‍❤️‍👩🏽,👩🏻‍❤️‍👩🏾,👩🏻‍❤️‍👩🏿,👩🏼‍❤️‍👩🏻,👩🏼‍❤️‍👩🏼,👩🏼‍❤️‍👩🏽,👩🏼‍❤️‍👩🏾,👩🏼‍❤️‍👩🏿,👩🏽‍❤️‍👩🏻,👩🏽‍❤️‍👩🏼,👩🏽‍❤️‍👩🏽,👩🏽‍❤️‍👩🏾,👩🏽‍❤️‍👩🏿,👩🏾‍❤️‍👩🏻,👩🏾‍❤️‍👩🏼,👩🏾‍❤️‍👩🏽,👩🏾‍❤️‍👩🏾,👩🏾‍❤️‍👩🏿,👩🏿‍❤️‍👩🏻,👩🏿‍❤️‍👩🏼,👩🏿‍❤️‍👩🏽,👩🏿‍❤️‍👩🏾,👩🏿‍❤️‍👩🏿 +🫄,🫄,🫄🏻,🫄🏼,🫄🏽,🫄🏾,🫄🏿,🤰,🤰🏻,🤰🏼,🤰🏽,🤰🏾,🤰🏿,🫃,🫃🏻,🫃🏼,🫃🏽,🫃🏾,🫃🏿 +🤱,🤱,🤱🏻,🤱🏼,🤱🏽,🤱🏾,🤱🏿 +🧑‍🍼,🧑‍🍼,🧑🏻‍🍼,🧑🏼‍🍼,🧑🏽‍🍼,🧑🏾‍🍼,🧑🏿‍🍼,👩‍🍼,👩🏻‍🍼,👩🏼‍🍼,👩🏽‍🍼,👩🏾‍🍼,👩🏿‍🍼,👨‍🍼,👨🏻‍🍼,👨🏼‍🍼,👨🏽‍🍼,👨🏾‍🍼,👨🏿‍🍼 diff --git a/emojipicker/app/src/main/res/raw/emoji_category_symbols.csv b/emojipicker/app/src/main/res/raw/emoji_category_symbols.csv new file mode 100644 index 000000000..d917e2747 --- /dev/null +++ b/emojipicker/app/src/main/res/raw/emoji_category_symbols.csv @@ -0,0 +1,261 @@ +🔴 +🟠 +🟡 +🟢 +🔵 +🟣 +🟤 +⚫ +⚪ +🟥 +🟧 +🟨 +🟩 +🟦 +🟪 +🟫 +⬛ +⬜ +❤️ +🧡 +💛 +💚 +💙 +💜 +🤎 +🖤 +🤍 +🩷 +🩵 +🩶 +♥️ +♦️ +♣️ +♠️ +♈ +♉ +♊ +♋ +♌ +♍ +♎ +♏ +♐ +♑ +♒ +♓ +⛎ +♀️ +♂️ +⚧️ +💭 +🗯️ +💬 +🗨️ +❕ +❔ +❗ +❓ +⁉️ +‼️ +⭕ +❌ +🚫 +🚳 +🚭 +🚯 +🚱 +🚷 +📵 +🔞 +🔕 +🔇 +🅰️ +🆎 +🅱️ +🅾️ +🆑 +🆘 +🛑 +⛔ +📛 +♨️ +💢 +🔻 +🔺 +🉐 +㊙️ +㊗️ +🈴 +🈵 +🈹 +🈲 +🉑 +🈶 +🈚 +🈸 +🈺 +🈷️ +✴️ +🔶 +🔸 +🔆 +🔅 +🆚 +🎦 +📶 +🔁 +🔂 +🔀 +▶️ +⏩ +⏭️ +⏯️ +◀️ +⏪ +⏮️ +🔼 +⏫ +🔽 +⏬ +⏸️ +⏹️ +⏺️ +⏏️ +📴 +🛜 +📳 +📲 +☢️ +☣️ +⚠️ +🚸 +⚜️ +🔱 +〽️ +🔰 +✳️ +❇️ +♻️ +💱 +💲 +💹 +🈯 +❎ +✅ +✔️ +☑️ +⬆️ +↗️ +➡️ +↘️ +⬇️ +↙️ +⬅️ +↖️ +↕️ +↔️ +↩️ +↪️ +⤴️ +⤵️ +🔃 +🔄 +🔙 +🔛 +🔝 +🔚 +🔜 +🆕 +🆓 +🆙 +🆗 +🆒 +🆖 +ℹ️ +🅿️ +🈁 +🈂️ +🈳 +🔣 +🔤 +🔠 +🔡 +🔢 +#️⃣ +*️⃣ +0️⃣ +1️⃣ +2️⃣ +3️⃣ +4️⃣ +5️⃣ +6️⃣ +7️⃣ +8️⃣ +9️⃣ +🔟 +🌐 +💠 +🔷 +🔹 +🏧 +Ⓜ️ +🚾 +🚻 +🚹 +🚺 +♿ +🚼 +🛗 +🚮 +🚰 +🛂 +🛃 +🛄 +🛅 +💟 +⚛️ +🛐 +🕉️ +☸️ +☮️ +☯️ +☪️ +🪯 +✝️ +☦️ +✡️ +🔯 +🕎 +♾️ +🆔 +🧑‍🧑‍🧒 +🧑‍🧑‍🧒‍🧒 +🧑‍🧒 +🧑‍🧒‍🧒 +⚕️ +🎼 +🎵 +🎶 +✖️ +➕ +➖ +➗ +🟰 +➰ +➿ +〰️ +©️ +®️ +™️ +🔘 +🔳 +◼️ +◾ +▪️ +🔲 +◻️ +◽ +▫️ +👁️‍🗨️ diff --git a/emojipicker/app/src/main/res/raw/emoji_category_travel_places.csv b/emojipicker/app/src/main/res/raw/emoji_category_travel_places.csv new file mode 100644 index 000000000..8704e9563 --- /dev/null +++ b/emojipicker/app/src/main/res/raw/emoji_category_travel_places.csv @@ -0,0 +1,122 @@ +🛑 +🚧 +🚨 +⛽ +🛢️ +🧭 +🛞 +🛟 +⚓ +🚏 +🚇 +🚥 +🚦 +🛴 +🦽 +🦼 +🩼 +🚲 +🛵 +🏍️ +🚙 +🚗 +🛻 +🚐 +🚚 +🚛 +🚜 +🏎️ +🚒 +🚑 +🚓 +🚕 +🛺 +🚌 +🚈 +🚝 +🚅 +🚄 +🚂 +🚃 +🚋 +🚎 +🚞 +🚊 +🚉 +🚍 +🚔 +🚘 +🚖 +🚆 +🚢 +🛳️ +🛥️ +🚤 +⛴️ +⛵ +🛶 +🚟 +🚠 +🚡 +🚁 +🛸 +🚀 +✈️ +🛫 +🛬 +🛩️ +🛝 +🎢 +🎡 +🎠 +🎪 +🗼 +🗽 +🗿 +🗻 +🏛️ +💈 +⛲ +⛩️ +🕍 +🕌 +🕋 +🛕 +⛪ +💒 +🏩 +🏯 +🏰 +🏗️ +🏢 +🏭 +🏬 +🏪 +🏟️ +🏦 +🏫 +🏨 +🏣 +🏤 +🏥 +🏚️ +🏠 +🏡 +🏘️ +🛖 +⛺ +🏕️ +⛱️ +🏙️ +🌆 +🌇 +🌃 +🌉 +🌁 +🛤️ +🛣️ +🗾 +🗺️ +🌐 +💺 +🧳 diff --git a/emojipicker/app/src/main/res/values-af/strings.xml b/emojipicker/app/src/main/res/values-af/strings.xml new file mode 100644 index 000000000..ef7bb7c44 --- /dev/null +++ b/emojipicker/app/src/main/res/values-af/strings.xml @@ -0,0 +1,42 @@ + + + + + "ONLANGS GEBRUIK" + "EMOSIEKONE EN EMOSIES" + "MENSE" + "DIERE EN NATUUR" + "KOS EN DRINKGOED" + "REIS EN PLEKKE" + "AKTIWITEITE EN GELEENTHEDE" + "VOORWERPE" + "SIMBOLE" + "VLAE" + "Geen emosiekone beskikbaar nie" + "Jy het nog geen emosiekone gebruik nie" + "emosiekoon-tweerigtingoorskakelaar" + "rigting waarin emosiekoon wys is gewissel" + "emosiekoonvariantkieser" + "%1$s en %2$s" + "skadu" + "ligte velkleur" + "mediumligte velkleur" + "medium velkleur" + "mediumdonker velkleur" + "donker velkleur" + diff --git a/emojipicker/app/src/main/res/values-am/strings.xml b/emojipicker/app/src/main/res/values-am/strings.xml new file mode 100644 index 000000000..5be491cca --- /dev/null +++ b/emojipicker/app/src/main/res/values-am/strings.xml @@ -0,0 +1,42 @@ + + + + + "በቅርብ ጊዜ ጥቅም ላይ የዋለ" + "ሳቂታዎች እና ስሜቶች" + "ሰዎች" + "እንስሳት እና ተፈጥሮ" + "ምግብ እና መጠጥ" + "ጉዞ እና ቦታዎች" + "እንቅስቃሴዎች እና ክስተቶች" + "ነገሮች" + "ምልክቶች" + "ባንዲራዎች" + "ምንም ስሜት ገላጭ ምስሎች አይገኙም" + "ምንም ስሜት ገላጭ ምስሎችን እስካሁን አልተጠቀሙም" + "የስሜት ገላጭ ምስል ባለሁለት አቅጣጫ መቀያየሪያ" + "የስሜት ገላጭ ምስል አቅጣጫ ተቀይሯል" + "የስሜት ገላጭ ምስል ተለዋዋጭ መራጭ" + "%1$s እና %2$s" + "ጥላ" + "ነጣ ያለ የቆዳ ቀለም" + "መካከለኛ ነጣ ያለ የቆዳ ቀለም" + "መካከለኛ የቆዳ ቀለም" + "መካከለኛ ጠቆር ያለ የቆዳ ቀለም" + "ጠቆር ያለ የቆዳ ቀለም" + diff --git a/emojipicker/app/src/main/res/values-ar/strings.xml b/emojipicker/app/src/main/res/values-ar/strings.xml new file mode 100644 index 000000000..4d42ff9e9 --- /dev/null +++ b/emojipicker/app/src/main/res/values-ar/strings.xml @@ -0,0 +1,42 @@ + + + + + "المستخدمة حديثًا" + "الوجوه المبتسمة والرموز التعبيرية" + "الأشخاص" + "الحيوانات والطبيعة" + "المأكولات والمشروبات" + "السفر والأماكن" + "الأنشطة والأحداث" + "عناصر متنوعة" + "الرموز" + "الأعلام" + "لا تتوفر أي رموز تعبيرية." + "لم تستخدم أي رموز تعبيرية حتى الآن." + "مفتاح ثنائي الاتجاه للرموز التعبيرية" + "تم تغيير اتجاه الإيموجي" + "أداة اختيار الرموز التعبيرية" + "‏%1$s و%2$s" + "الظل" + "بشرة فاتحة" + "بشرة فاتحة متوسّطة" + "بشرة متوسّطة" + "بشرة داكنة متوسّطة" + "بشرة داكنة" + diff --git a/emojipicker/app/src/main/res/values-as/strings.xml b/emojipicker/app/src/main/res/values-as/strings.xml new file mode 100644 index 000000000..6ca5f5b7c --- /dev/null +++ b/emojipicker/app/src/main/res/values-as/strings.xml @@ -0,0 +1,42 @@ + + + + + "অলপতে ব্যৱহৃত" + "স্মাইলী আৰু আৱেগ" + "মানুহ" + "পশু আৰু প্ৰকৃতি" + "খাদ্য আৰু পানীয়" + "ভ্ৰমণ আৰু স্থান" + "কাৰ্যকলাপ আৰু অনুষ্ঠান" + "বস্তু" + "চিহ্ন" + "পতাকা" + "কোনো ইম’জি উপলব্ধ নহয়" + "আপুনি এতিয়ালৈকে কোনো ইম’জি ব্যৱহাৰ কৰা নাই" + "ইম’জি বাইডাইৰেকশ্বনেল ছুইচ্চাৰ" + "দিক্-নিৰ্দেশনা প্ৰদৰ্শন কৰা ইম’জি সলনি কৰা হৈছে" + "ইম’জিৰ প্ৰকাৰ বাছনি কৰোঁতা" + "%1$s আৰু %2$s" + "ছাঁ" + "পাতলীয়া ছালৰ ৰং" + "মধ্যমীয়া পাতল ছালৰ ৰং" + "মিঠাবৰণীয়া ছালৰ ৰং" + "মধ্যমীয়া গাঢ় ছালৰ ৰং" + "গাঢ় ছালৰ ৰং" + diff --git a/emojipicker/app/src/main/res/values-az/strings.xml b/emojipicker/app/src/main/res/values-az/strings.xml new file mode 100644 index 000000000..c4c528575 --- /dev/null +++ b/emojipicker/app/src/main/res/values-az/strings.xml @@ -0,0 +1,42 @@ + + + + + "SON İSTİFADƏ EDİLƏN" + "SMAYLİK VƏ EMOSİYALAR" + "ADAMLAR" + "HEYVANLAR VƏ TƏBİƏT" + "QİDA VƏ İÇKİ" + "SƏYAHƏT VƏ MƏKANLAR" + "FƏALİYYƏTLƏR VƏ TƏDBİRLƏR" + "OBYEKTLƏR" + "SİMVOLLAR" + "BAYRAQLAR" + "Əlçatan emoji yoxdur" + "Hələ heç bir emojidən istifadə etməməsiniz" + "ikitərəfli emoji dəyişdirici" + "emoji istiqaməti dəyişdirildi" + "emoji variant seçicisi" + "%1$s və %2$s" + "kölgə" + "açıq dəri rəngi" + "orta açıq dəri rəngi" + "orta dəri rəngi" + "orta tünd dəri rəngi" + "tünd dəri rəngi" + diff --git a/emojipicker/app/src/main/res/values-b+sr+Latn/strings.xml b/emojipicker/app/src/main/res/values-b+sr+Latn/strings.xml new file mode 100644 index 000000000..8feb29612 --- /dev/null +++ b/emojipicker/app/src/main/res/values-b+sr+Latn/strings.xml @@ -0,0 +1,42 @@ + + + + + "NEDAVNO KORIŠĆENO" + "SMAJLIJI I EMOCIJE" + "LJUDI" + "ŽIVOTINJE I PRIRODA" + "HRANA I PIĆE" + "PUTOVANJA I MESTA" + "AKTIVNOSTI I DOGAĐAJI" + "OBJEKTI" + "SIMBOLI" + "ZASTAVE" + "Emodžiji nisu dostupni" + "Još niste koristili emodžije" + "dvosmerni prebacivač emodžija" + "smer emodžija je promenjen" + "birač varijanti emodžija" + "%1$s i %2$s" + "senka" + "koža svetle puti" + "koža srednjesvetle puti" + "koža srednje puti" + "koža srednjetamne puti" + "koža tamne puti" + diff --git a/emojipicker/app/src/main/res/values-be/strings.xml b/emojipicker/app/src/main/res/values-be/strings.xml new file mode 100644 index 000000000..67dc3c2e6 --- /dev/null +++ b/emojipicker/app/src/main/res/values-be/strings.xml @@ -0,0 +1,42 @@ + + + + + "НЯДАЎНА ВЫКАРЫСТАНЫЯ" + "СМАЙЛІКІ І ЭМОЦЫІ" + "ЛЮДЗІ" + "ЖЫВЁЛЫ І ПРЫРОДА" + "ЕЖА І НАПОІ" + "ПАДАРОЖЖЫ І МЕСЦЫ" + "ДЗЕЯННІ І ПАДЗЕІ" + "АБ\'ЕКТЫ" + "СІМВАЛЫ" + "СЦЯГІ" + "Няма даступных эмодзі" + "Вы пакуль не выкарыстоўвалі эмодзі" + "пераключальнік кірунку для эмодзі" + "кірунак арыентацыі эмодзі зменены" + "інструмент выбару варыянтаў эмодзі" + "%1$s і %2$s" + "цень" + "светлы колер скуры" + "умерана светлы колер скуры" + "нейтральны колер скуры" + "умерана цёмны колер скуры" + "цёмны колер скуры" + diff --git a/emojipicker/app/src/main/res/values-bg/strings.xml b/emojipicker/app/src/main/res/values-bg/strings.xml new file mode 100644 index 000000000..929d7676e --- /dev/null +++ b/emojipicker/app/src/main/res/values-bg/strings.xml @@ -0,0 +1,42 @@ + + + + + "НАСКОРО ИЗПОЛЗВАНИ" + "ЕМОТИКОНИ И ЕМОЦИИ" + "ХОРА" + "ЖИВОТНИ И ПРИРОДА" + "ХРАНИ И НАПИТКИ" + "ПЪТУВАНИЯ И МЕСТА" + "АКТИВНОСТИ И СЪБИТИЯ" + "ПРЕДМЕТИ" + "СИМВОЛИ" + "ЗНАМЕНА" + "Няма налични емоджи" + "Все още не сте използвали емоджита" + "двупосочен превключвател на емоджи" + "посоката на емоджи бе променена" + "инструмент за избор на варианти за емоджи" + "%1$s и %2$s" + "сянка" + "светъл цвят на кожата" + "средно светъл цвят на кожата" + "междинен цвят на кожата" + "средно тъмен цвят на кожата" + "тъмен цвят на кожата" + diff --git a/emojipicker/app/src/main/res/values-bn/strings.xml b/emojipicker/app/src/main/res/values-bn/strings.xml new file mode 100644 index 000000000..55a691f28 --- /dev/null +++ b/emojipicker/app/src/main/res/values-bn/strings.xml @@ -0,0 +1,42 @@ + + + + + "সম্প্রতি ব্যবহার করা হয়েছে" + "স্মাইলি ও আবেগ" + "ব্যক্তি" + "প্রাণী ও প্রকৃতি" + "খাদ্য ও পানীয়" + "ভ্রমণ ও জায়গা" + "অ্যাক্টিভিটি ও ইভেন্ট" + "অবজেক্ট" + "প্রতীক" + "ফ্ল্যাগ" + "কোনও ইমোজি উপলভ্য নেই" + "আপনি এখনও কোনও ইমোজি ব্যবহার করেননি" + "ইমোজি দ্বিমুখী সুইচার" + "ইমোজির দিক পরিবর্তন হয়েছে" + "ইমোজি ভেরিয়েন্ট বাছাইকারী" + "%1$s এবং %2$s" + "ছায়া" + "হাল্কা স্কিন টোন" + "মাঝারি-হাল্কা স্কিন টোন" + "মাঝারি স্কিন টোন" + "মাঝারি-গাঢ় স্কিন টোন" + "গাঢ় স্কিন টোন" + diff --git a/emojipicker/app/src/main/res/values-bs/strings.xml b/emojipicker/app/src/main/res/values-bs/strings.xml new file mode 100644 index 000000000..401f6c827 --- /dev/null +++ b/emojipicker/app/src/main/res/values-bs/strings.xml @@ -0,0 +1,42 @@ + + + + + "NEDAVNO KORIŠTENO" + "SMAJLIJI I EMOCIJE" + "OSOBE" + "ŽIVOTINJE I PRIRODA" + "HRANA I PIĆE" + "PUTOVANJA I MJESTA" + "AKTIVNOSTI I DOGAĐAJI" + "PREDMETI" + "SIMBOLI" + "ZASTAVE" + "Emoji sličice nisu dostupne" + "Još niste koristili nijednu emoji sličicu" + "dvosmjerni prebacivač emodžija" + "emodži gleda u smjeru postavke prekidača" + "birač varijanti emodžija" + "%1$s i %2$s" + "sjenka" + "svijetla boja kože" + "srednje svijetla boja kože" + "srednja boja kože" + "srednje tamna boja kože" + "tamna boja kože" + diff --git a/emojipicker/app/src/main/res/values-ca/strings.xml b/emojipicker/app/src/main/res/values-ca/strings.xml new file mode 100644 index 000000000..09e2bc9a8 --- /dev/null +++ b/emojipicker/app/src/main/res/values-ca/strings.xml @@ -0,0 +1,42 @@ + + + + + "UTILITZATS FA POC" + "EMOTICONES I EMOCIONS" + "PERSONES" + "ANIMALS I NATURALESA" + "MENJAR I BEGUDA" + "VIATGES I LLOCS" + "ACTIVITATS I ESDEVENIMENTS" + "OBJECTES" + "SÍMBOLS" + "BANDERES" + "No hi ha cap emoji disponible" + "Encara no has fet servir cap emoji" + "selector bidireccional d\'emojis" + "s\'ha canviat la direcció de l\'emoji" + "selector de variants d\'emojis" + "%1$s i %2$s" + "ombra" + "to de pell clar" + "to de pell mitjà-clar" + "to de pell mitjà" + "to de pell mitjà-fosc" + "to de pell fosc" + diff --git a/emojipicker/app/src/main/res/values-cs/strings.xml b/emojipicker/app/src/main/res/values-cs/strings.xml new file mode 100644 index 000000000..8d7e0f502 --- /dev/null +++ b/emojipicker/app/src/main/res/values-cs/strings.xml @@ -0,0 +1,42 @@ + + + + + "NEDÁVNO POUŽITÉ" + "SMAJLÍCI A EMOCE" + "LIDÉ" + "ZVÍŘATA A PŘÍRODA" + "JÍDLO A PITÍ" + "CESTOVÁNÍ A MÍSTA" + "AKTIVITY A UDÁLOSTI" + "OBJEKTY" + "SYMBOLY" + "VLAJKY" + "Nejsou k dispozici žádné smajlíky" + "Zatím jste žádná emodži nepoužili" + "dvousměrný přepínač smajlíků" + "směr pohledu smajlíků přepnut" + "výběr variant emodži" + "%1$s a %2$s" + "stín" + "světlý tón pleti" + "středně světlý tón pleti" + "střední tón pleti" + "středně tmavý tón pleti" + "tmavý tón pleti" + diff --git a/emojipicker/app/src/main/res/values-da/strings.xml b/emojipicker/app/src/main/res/values-da/strings.xml new file mode 100644 index 000000000..e9eb67b95 --- /dev/null +++ b/emojipicker/app/src/main/res/values-da/strings.xml @@ -0,0 +1,42 @@ + + + + + "BRUGT FOR NYLIG" + "SMILEYS OG HUMØRIKONER" + "PERSONER" + "DYR OG NATUR" + "MAD OG DRIKKE" + "REJSER OG STEDER" + "AKTIVITETER OG BEGIVENHEDER" + "TING" + "SYMBOLER" + "FLAG" + "Der er ingen tilgængelige emojis" + "Du har ikke brugt nogen emojis endnu" + "tovejsskifter til emojis" + "emojien vender en anden retning" + "vælger for emojivariant" + "%1$s og %2$s" + "skygge" + "lys hudfarve" + "mellemlys hudfarve" + "medium hudfarve" + "mellemmørk hudfarve" + "mørk hudfarve" + diff --git a/emojipicker/app/src/main/res/values-de/strings.xml b/emojipicker/app/src/main/res/values-de/strings.xml new file mode 100644 index 000000000..6e72ab753 --- /dev/null +++ b/emojipicker/app/src/main/res/values-de/strings.xml @@ -0,0 +1,42 @@ + + + + + "ZULETZT VERWENDET" + "SMILEYS UND EMOTIONEN" + "PERSONEN" + "TIERE UND NATUR" + "ESSEN UND TRINKEN" + "REISEN UND ORTE" + "AKTIVITÄTEN UND EVENTS" + "OBJEKTE" + "SYMBOLE" + "FLAGGEN" + "Keine Emojis verfügbar" + "Du hast noch keine Emojis verwendet" + "Bidirektionale Emoji-Auswahl" + "Emoji-Richtung geändert" + "Emojivarianten-Auswahl" + "%1$s und %2$s" + "Hautton" + "Heller Hautton" + "Mittelheller Hautton" + "Mittlerer Hautton" + "Mitteldunkler Hautton" + "Dunkler Hautton" + diff --git a/emojipicker/app/src/main/res/values-el/strings.xml b/emojipicker/app/src/main/res/values-el/strings.xml new file mode 100644 index 000000000..4a59ed678 --- /dev/null +++ b/emojipicker/app/src/main/res/values-el/strings.xml @@ -0,0 +1,42 @@ + + + + + "ΧΡΗΣΙΜΟΠΟΙΗΘΗΚΑΝ ΠΡΟΣΦΑΤΑ" + "ΕΙΚΟΝΙΔΙΑ SMILEY ΚΑΙ ΣΥΝΑΙΣΘΗΜΑΤΑ" + "ΑΤΟΜΑ" + "ΖΩΑ ΚΑΙ ΦΥΣΗ" + "ΦΑΓΗΤΟ ΚΑΙ ΠΟΤΟ" + "ΤΑΞΙΔΙΑ ΚΑΙ ΜΕΡΗ" + "ΔΡΑΣΤΗΡΙΟΤΗΤΕΣ ΚΑΙ ΣΥΜΒΑΝΤΑ" + "ΑΝΤΙΚΕΙΜΕΝΑ" + "ΣΥΜΒΟΛΑ" + "ΣΗΜΑΙΕΣ" + "Δεν υπάρχουν διαθέσιμα emoji" + "Δεν έχετε χρησιμοποιήσει κανένα emoji ακόμα" + "αμφίδρομο στοιχείο εναλλαγής emoji" + "έγινε εναλλαγή της κατεύθυνσης που είναι στραμμένο το emoji" + "επιλογέας παραλλαγής emoji" + "%1$s και %2$s" + "σκιά" + "ανοιχτός τόνος επιδερμίδας" + "μεσαίος προς ανοιχτός τόνος επιδερμίδας" + "μεσαίος τόνος επιδερμίδας" + "μεσαίος προς σκούρος τόνος επιδερμίδας" + "σκούρος τόνος επιδερμίδας" + diff --git a/emojipicker/app/src/main/res/values-en-rAU/strings.xml b/emojipicker/app/src/main/res/values-en-rAU/strings.xml new file mode 100644 index 000000000..0b651f515 --- /dev/null +++ b/emojipicker/app/src/main/res/values-en-rAU/strings.xml @@ -0,0 +1,42 @@ + + + + + "RECENTLY USED" + "SMILEYS AND EMOTIONS" + "PEOPLE" + "ANIMALS AND NATURE" + "FOOD AND DRINK" + "TRAVEL AND PLACES" + "ACTIVITIES AND EVENTS" + "OBJECTS" + "SYMBOLS" + "FLAGS" + "No emojis available" + "You haven\'t used any emoji yet" + "emoji bidirectional switcher" + "emoji facing direction switched" + "emoji variant selector" + "%1$s and %2$s" + "shadow" + "light skin tone" + "medium-light skin tone" + "medium skin tone" + "medium-dark skin tone" + "dark skin tone" + diff --git a/emojipicker/app/src/main/res/values-en-rCA/strings.xml b/emojipicker/app/src/main/res/values-en-rCA/strings.xml new file mode 100644 index 000000000..d056590cc --- /dev/null +++ b/emojipicker/app/src/main/res/values-en-rCA/strings.xml @@ -0,0 +1,42 @@ + + + + + "RECENTLY USED" + "SMILEYS AND EMOTIONS" + "PEOPLE" + "ANIMALS AND NATURE" + "FOOD AND DRINK" + "TRAVEL AND PLACES" + "ACTIVITIES AND EVENTS" + "OBJECTS" + "SYMBOLS" + "FLAGS" + "No emojis available" + "You haven\'t used any emojis yet" + "emoji bidirectional switcher" + "emoji facing direction switched" + "emoji variant selector" + "%1$s and %2$s" + "shadow" + "light skin tone" + "medium light skin tone" + "medium skin tone" + "medium dark skin tone" + "dark skin tone" + diff --git a/emojipicker/app/src/main/res/values-en-rGB/strings.xml b/emojipicker/app/src/main/res/values-en-rGB/strings.xml new file mode 100644 index 000000000..0b651f515 --- /dev/null +++ b/emojipicker/app/src/main/res/values-en-rGB/strings.xml @@ -0,0 +1,42 @@ + + + + + "RECENTLY USED" + "SMILEYS AND EMOTIONS" + "PEOPLE" + "ANIMALS AND NATURE" + "FOOD AND DRINK" + "TRAVEL AND PLACES" + "ACTIVITIES AND EVENTS" + "OBJECTS" + "SYMBOLS" + "FLAGS" + "No emojis available" + "You haven\'t used any emoji yet" + "emoji bidirectional switcher" + "emoji facing direction switched" + "emoji variant selector" + "%1$s and %2$s" + "shadow" + "light skin tone" + "medium-light skin tone" + "medium skin tone" + "medium-dark skin tone" + "dark skin tone" + diff --git a/emojipicker/app/src/main/res/values-en-rIN/strings.xml b/emojipicker/app/src/main/res/values-en-rIN/strings.xml new file mode 100644 index 000000000..0b651f515 --- /dev/null +++ b/emojipicker/app/src/main/res/values-en-rIN/strings.xml @@ -0,0 +1,42 @@ + + + + + "RECENTLY USED" + "SMILEYS AND EMOTIONS" + "PEOPLE" + "ANIMALS AND NATURE" + "FOOD AND DRINK" + "TRAVEL AND PLACES" + "ACTIVITIES AND EVENTS" + "OBJECTS" + "SYMBOLS" + "FLAGS" + "No emojis available" + "You haven\'t used any emoji yet" + "emoji bidirectional switcher" + "emoji facing direction switched" + "emoji variant selector" + "%1$s and %2$s" + "shadow" + "light skin tone" + "medium-light skin tone" + "medium skin tone" + "medium-dark skin tone" + "dark skin tone" + diff --git a/emojipicker/app/src/main/res/values-en-rXC/strings.xml b/emojipicker/app/src/main/res/values-en-rXC/strings.xml new file mode 100644 index 000000000..3e02185f4 --- /dev/null +++ b/emojipicker/app/src/main/res/values-en-rXC/strings.xml @@ -0,0 +1,42 @@ + + + + + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‏‏‏‏‎‏‏‎‏‎‎‎‏‏‎‏‎‏‎‏‏‏‏‏‎‏‏‎‏‏‎‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎‎‏‎‎‏‏‏‎RECENTLY USED‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‏‏‎‎‏‎‏‏‎‏‏‎‎‏‏‏‎‎‎‏‏‏‎‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‎‏‎‎‏‏‏‎‎‎‎‎‏‎SMILEYS AND EMOTIONS‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‎‏‎‎‏‎‏‎‎‎‏‏‎‏‏‏‎‏‎‏‏‎‏‏‏‏‏‎‎‎‏‏‎‏‎‏‎‏‏‏‏‎‏‎‏‎‏‏‎‎‎‏‎PEOPLE‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‎‎‏‏‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‏‎‏‎‎‏‏‏‎‎‏‎‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‎‎‏‎‏‎‏‎ANIMALS AND NATURE‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‎‎‎‎‏‎‎‎‏‏‎‎‏‎‏‎‏‎‏‎‎‏‎‎‏‎‏‎‎‏‏‏‏‎‎‎‎‏‏‏‎‏‎‏‏‎FOOD AND DRINK‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‏‏‎‏‎‎‏‎‎‏‎‎‎‏‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‎‎‎‏‏‎‎‎‎‎‎‎TRAVEL AND PLACES‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‏‎‎‏‏‏‎‏‎‏‏‎‎‏‎‏‏‎‎‏‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‎ACTIVITIES AND EVENTS‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‏‎‏‎‎‎‏‏‏‏‏‎‎‎‏‏‎‎‎‏‏‎‎‎‎‏‏‎‏‎‏‏‎‎‏‎‎‏‏‎‎‏‏‏‎‎‎‏‏‎OBJECTS‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‏‎‏‎‎‎‎‏‎‏‏‎‏‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‏‏‏‎‎‎‎‏‏‎‎‎‎‎‎‎‏‏‎‏‏‎SYMBOLS‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‎‏‏‏‏‏‎‎‏‏‏‎‎‏‎‏‏‎‏‏‎‎‎‎‎‏‎‎‏‎‏‏‎‎‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‏‎FLAGS‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‎‏‎‎‎‎‏‏‎‏‎‏‏‎‏‎‏‏‎‎‎‎‎‎‎‏‎‏‎‏‎‎‏‏‎‎‎‎‎‏‎‏‎‎‏‎‏‎‎‎‏‎No emojis available‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‎‎‎‏‎‎‎‎‏‏‎‏‏‎‎‏‏‏‎‎‎‎‏‎‎‎‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎‎‏‎‏‎‏‎‏‏‎‎‎‎You haven\'t used any emojis yet‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‏‎‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‎‎‏‏‏‏‎‏‎‏‏‏‎‏‎‎‏‎‏‎‎‎‎‏‎‏‎‎‎‏‏‏‏‎‏‎emoji bidirectional switcher‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‏‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‎‎‎‎‎‏‏‎emoji facing direction switched‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‎‏‏‏‏‎‏‎‏‎‏‏‎‏‎‎‎‏‎‎‏‎‎‏‎‎‎‏‏‎‏‎‏‎‎‏‏‎‎‎‎‎‎emoji variant selector‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‏‎‎‎‏‎‎‏‎‏‏‏‎‎‏‎‎‏‎‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‎‏‎‏‎‎‎‏‎‏‏‏‏‎‏‎‎‎‏‎%1$s and %2$s‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‏‏‎‏‏‎‎‎‏‏‏‎‎‎‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‏‎‏‎‎‏‏‏‏‎‎‎‎‏‏‏‎‏‎‏‏‎‎‎‎‎shadow‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‏‎‏‎‎‏‎‎‏‏‎‏‏‏‎‏‎‏‎‏‎‎‏‎‏‏‎‏‎‎‎‎‎‏‎‎‏‏‎‎‎‏‏‏‏‎‎‏‎‎‎‏‎light skin tone‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‏‎‎‏‎‎‏‏‏‎‎‎‎‎‏‏‏‏‏‏‎‎‏‏‎‏‏‎‎‎‎‎‏‏‎‎‏‎‏‎‏‏‎‏‏‎‏‏‎‏‎‏‎‎medium light skin tone‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‏‏‎‏‏‎‏‎‎‏‎‏‏‏‏‎‏‎‎‎‎‎‎‏‎‏‎‏‏‎‎‏‏‎‏‏‏‎‎‎‏‎‎‎‎‎‏‏‎medium skin tone‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‏‎‏‎‏‎‎‏‏‏‎‎‏‎‎‎‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‏‏‏‎‎‎‏‎‏‏‏‏‎‏‎‏‎‏‎‏‏‎‏‎medium dark skin tone‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‏‎‎‏‎‏‎‏‎‎‎‎‏‎‏‎‏‏‎‎‎‎‏‎‎‎‏‏‎‎‎‎‎‎‏‏‏‎‎‏‏‎‎‏‏‏‏‎‏‏‏‎‎dark skin tone‎‏‎‎‏‎" + diff --git a/emojipicker/app/src/main/res/values-es-rUS/strings.xml b/emojipicker/app/src/main/res/values-es-rUS/strings.xml new file mode 100644 index 000000000..e9001edfe --- /dev/null +++ b/emojipicker/app/src/main/res/values-es-rUS/strings.xml @@ -0,0 +1,42 @@ + + + + + "USADOS RECIENTEMENTE" + "EMOTICONES Y EMOCIONES" + "PERSONAS" + "ANIMALES Y NATURALEZA" + "COMIDAS Y BEBIDAS" + "VIAJES Y LUGARES" + "ACTIVIDADES Y EVENTOS" + "OBJETOS" + "SÍMBOLOS" + "BANDERAS" + "No hay ningún emoji disponible" + "Todavía no usaste ningún emoji" + "selector bidireccional de emojis" + "se cambió la dirección del emoji" + "selector de variantes de emojis" + "%1$s y %2$s" + "sombra" + "tono de piel claro" + "tono de piel medio claro" + "tono de piel intermedio" + "tono de piel medio oscuro" + "tono de piel oscuro" + diff --git a/emojipicker/app/src/main/res/values-es/strings.xml b/emojipicker/app/src/main/res/values-es/strings.xml new file mode 100644 index 000000000..d2aed3688 --- /dev/null +++ b/emojipicker/app/src/main/res/values-es/strings.xml @@ -0,0 +1,42 @@ + + + + + "USADOS RECIENTEMENTE" + "EMOTICONOS Y EMOCIONES" + "PERSONAS" + "ANIMALES Y NATURALEZA" + "COMIDA Y BEBIDA" + "VIAJES Y SITIOS" + "ACTIVIDADES Y EVENTOS" + "OBJETOS" + "SÍMBOLOS" + "BANDERAS" + "No hay emojis disponibles" + "Aún no has usado ningún emoji" + "cambio bidireccional de emojis" + "dirección a la que se orienta el emoji cambiada" + "selector de variantes de emojis" + "%1$s y %2$s" + "sombra" + "tono de piel claro" + "tono de piel medio claro" + "tono de piel medio" + "tono de piel medio oscuro" + "tono de piel oscuro" + diff --git a/emojipicker/app/src/main/res/values-et/strings.xml b/emojipicker/app/src/main/res/values-et/strings.xml new file mode 100644 index 000000000..8b3d05aa9 --- /dev/null +++ b/emojipicker/app/src/main/res/values-et/strings.xml @@ -0,0 +1,42 @@ + + + + + "HILJUTI KASUTATUD" + "NÄOIKOONID JA EMOTSIOONID" + "INIMESED" + "LOOMAD JA LOODUS" + "SÖÖK JA JOOK" + "REISIMINE JA KOHAD" + "TEGEVUSED JA SÜNDMUSED" + "OBJEKTID" + "SÜMBOLID" + "LIPUD" + "Ühtegi emotikoni pole saadaval" + "Te pole veel ühtegi emotikoni kasutanud" + "emotikoni kahesuunaline lüliti" + "emotikoni suunda vahetati" + "emotikoni variandi valija" + "%1$s ja %2$s" + "vari" + "hele nahatoon" + "keskmiselt hele nahatoon" + "keskmine nahatoon" + "keskmiselt tume nahatoon" + "tume nahatoon" + diff --git a/emojipicker/app/src/main/res/values-eu/strings.xml b/emojipicker/app/src/main/res/values-eu/strings.xml new file mode 100644 index 000000000..9c550ca96 --- /dev/null +++ b/emojipicker/app/src/main/res/values-eu/strings.xml @@ -0,0 +1,42 @@ + + + + + "ERABILITAKO AZKENAK" + "AURPEGIERAK ETA ALDARTEAK" + "JENDEA" + "ANIMALIAK ETA NATURA" + "JAN-EDANAK" + "BIDAIAK ETA TOKIAK" + "JARDUERAK ETA GERTAERAK" + "OBJEKTUAK" + "IKURRAK" + "BANDERAK" + "Ez dago emotikonorik erabilgarri" + "Ez duzu erabili emojirik oraingoz" + "noranzko biko emoji-aldatzailea" + "emojiaren norabidea aldatu da" + "emojien aldaeren hautatzailea" + "%1$s eta %2$s" + "itzala" + "azalaren tonu argia" + "azalaren tonu argixka" + "azalaren tarteko tonua" + "azalaren tonu ilunxkoa" + "azalaren tonu iluna" + diff --git a/emojipicker/app/src/main/res/values-fa/strings.xml b/emojipicker/app/src/main/res/values-fa/strings.xml new file mode 100644 index 000000000..5930a4f02 --- /dev/null +++ b/emojipicker/app/src/main/res/values-fa/strings.xml @@ -0,0 +1,42 @@ + + + + + "اخیراً استفاده‌شده" + "شکلک‌ها و احساسات" + "افراد" + "حیوانات و طبیعت" + "غذا و نوشیدنی" + "سفر و مکان‌ها" + "فعالیت‌ها و رویدادها" + "اشیاء" + "نشان‌ها" + "پرچم‌ها" + "اموجی دردسترس نیست" + "هنوز از هیچ اموجی‌ای استفاده نکرده‌اید" + "تغییردهنده دوسویه اموجی" + "جهت چهره اموجی تغییر کرد" + "گزینشگر متغیر اموجی" + "‏%1$s و %2$s" + "سایه" + "رنگ‌مایه پوست روشن" + "رنگ‌مایه پوست ملایم روشن" + "رنگ‌مایه پوست ملایم" + "رنگ‌مایه پوست ملایم تیره" + "رنگ‌مایه پوست تیره" + diff --git a/emojipicker/app/src/main/res/values-fi/strings.xml b/emojipicker/app/src/main/res/values-fi/strings.xml new file mode 100644 index 000000000..bb6ccb586 --- /dev/null +++ b/emojipicker/app/src/main/res/values-fi/strings.xml @@ -0,0 +1,42 @@ + + + + + "VIIMEKSI KÄYTETYT" + "HYMIÖT JA TUNNETILAT" + "IHMISET" + "ELÄIMET JA LUONTO" + "RUOKA JA JUOMA" + "MATKAILU JA PAIKAT" + "AKTIVITEETIT JA TAPAHTUMAT" + "ESINEET" + "SYMBOLIT" + "LIPUT" + "Ei emojeita saatavilla" + "Et ole vielä käyttänyt emojeita" + "emoji kaksisuuntainen vaihtaja" + "emojin osoitussuunta vaihdettu" + "emojivalitsin" + "%1$s ja %2$s" + "varjostus" + "vaalea ihonväri" + "melko vaalea ihonväri" + "keskimääräinen ihonväri" + "melko tumma ihonväri" + "tumma ihonväri" + diff --git a/emojipicker/app/src/main/res/values-fr-rCA/strings.xml b/emojipicker/app/src/main/res/values-fr-rCA/strings.xml new file mode 100644 index 000000000..334f18f51 --- /dev/null +++ b/emojipicker/app/src/main/res/values-fr-rCA/strings.xml @@ -0,0 +1,42 @@ + + + + + "UTILISÉS RÉCEMMENT" + "ÉMOTICÔNES ET ÉMOTIONS" + "PERSONNES" + "ANIMAUX ET NATURE" + "ALIMENTS ET BOISSONS" + "VOYAGES ET LIEUX" + "ACTIVITÉS ET ÉVÉNEMENTS" + "OBJETS" + "SYMBOLES" + "DRAPEAUX" + "Aucun émoji proposé" + "Vous n\'avez encore utilisé aucun émoji" + "sélecteur bidirectionnel d\'émoji" + "Émoji tourné dans la direction inverse" + "sélecteur de variantes d\'émoji" + "%1$s et %2$s" + "ombre" + "teint clair" + "teint moyennement clair" + "teint moyen" + "teint moyennement foncé" + "teint foncé" + diff --git a/emojipicker/app/src/main/res/values-fr/strings.xml b/emojipicker/app/src/main/res/values-fr/strings.xml new file mode 100644 index 000000000..66f9f4d88 --- /dev/null +++ b/emojipicker/app/src/main/res/values-fr/strings.xml @@ -0,0 +1,42 @@ + + + + + "UTILISÉS RÉCEMMENT" + "ÉMOTICÔNES ET ÉMOTIONS" + "PERSONNES" + "ANIMAUX ET NATURE" + "ALIMENTATION ET BOISSONS" + "VOYAGES ET LIEUX" + "ACTIVITÉS ET ÉVÉNEMENTS" + "OBJETS" + "SYMBOLES" + "DRAPEAUX" + "Aucun emoji disponible" + "Vous n\'avez pas encore utilisé d\'emoji" + "sélecteur d\'emoji bidirectionnel" + "sens de l\'orientation de l\'emoji inversé" + "sélecteur de variante d\'emoji" + "%1$s et %2$s" + "ombre" + "teint clair" + "teint intermédiaire à clair" + "teint intermédiaire" + "teint intermédiaire à foncé" + "teint foncé" + diff --git a/emojipicker/app/src/main/res/values-gl/strings.xml b/emojipicker/app/src/main/res/values-gl/strings.xml new file mode 100644 index 000000000..f8715c36d --- /dev/null +++ b/emojipicker/app/src/main/res/values-gl/strings.xml @@ -0,0 +1,42 @@ + + + + + "USADOS HAI POUCO" + "ICONAS XESTUAIS E EMOTICONAS" + "PERSOAS" + "ANIMAIS E NATUREZA" + "COMIDA E BEBIDA" + "VIAXES E LUGARES" + "ACTIVIDADES E EVENTOS" + "OBXECTOS" + "SÍMBOLOS" + "BANDEIRAS" + "Non hai ningún emoji dispoñible" + "Aínda non utilizaches ningún emoji" + "selector bidireccional de emojis" + "dirección do emoji cambiada" + "selector de variantes de emojis" + "%1$s e %2$s" + "sombra" + "ton de pel claro" + "ton de pel lixeiramente claro" + "ton de pel medio" + "ton de pel lixeiramente escuro" + "ton de pel escuro" + diff --git a/emojipicker/app/src/main/res/values-gu/strings.xml b/emojipicker/app/src/main/res/values-gu/strings.xml new file mode 100644 index 000000000..dad9fd387 --- /dev/null +++ b/emojipicker/app/src/main/res/values-gu/strings.xml @@ -0,0 +1,42 @@ + + + + + "તાજેતરમાં વપરાયેલું" + "સ્માઇલી અને મનોભાવો" + "લોકો" + "પ્રાણીઓ અને પ્રકૃતિ" + "ભોજન અને પીણાં" + "મુસાફરી અને સ્થળો" + "પ્રવૃત્તિઓ અને ઇવેન્ટ" + "ઑબ્જેક્ટ" + "પ્રતીકો" + "ઝંડા" + "કોઈ ઇમોજી ઉપલબ્ધ નથી" + "તમે હજી સુધી કોઈ ઇમોજીનો ઉપયોગ કર્યો નથી" + "બે દિશામાં સ્વિચ થઈ શકતું ઇમોજી સ્વિચર" + "ઇમોજીની દિશા બદલવામાં આવી" + "ઇમોજીનો પ્રકાર પસંદગીકર્તા" + "%1$s અને %2$s" + "શૅડો" + "ત્વચાનો હળવો ટોન" + "ત્વચાનો મધ્યમ હળવો ટોન" + "ત્વચાનો મધ્યમ ટોન" + "ત્વચાનો મધ્યમ ઘેરો ટોન" + "ત્વચાનો ઘેરો ટોન" + diff --git a/emojipicker/app/src/main/res/values-hi/strings.xml b/emojipicker/app/src/main/res/values-hi/strings.xml new file mode 100644 index 000000000..81cd653a3 --- /dev/null +++ b/emojipicker/app/src/main/res/values-hi/strings.xml @@ -0,0 +1,42 @@ + + + + + "हाल ही में इस्तेमाल किए गए" + "स्माइली और भावनाएं" + "लोग" + "जानवर और प्रकृति" + "खाने-पीने की चीज़ें" + "यात्रा और जगहें" + "गतिविधियां और इवेंट" + "ऑब्जेक्ट" + "सिंबल" + "झंडे" + "कोई इमोजी उपलब्ध नहीं है" + "आपने अब तक किसी भी इमोजी का इस्तेमाल नहीं किया है" + "दोनों तरफ़ ले जा सकने वाले स्विचर का इमोजी" + "इमोजी को फ़्लिप किया गया" + "इमोजी के वैरिएंट चुनने का टूल" + "%1$s और %2$s" + "शैडो" + "हल्के रंग की त्वचा" + "थोड़े हल्के रंग की त्वचा" + "सामान्य रंग की त्वचा" + "थोड़े गहरे रंग की त्वचा" + "गहरे रंग की त्वचा" + diff --git a/emojipicker/app/src/main/res/values-hr/strings.xml b/emojipicker/app/src/main/res/values-hr/strings.xml new file mode 100644 index 000000000..481b48673 --- /dev/null +++ b/emojipicker/app/src/main/res/values-hr/strings.xml @@ -0,0 +1,42 @@ + + + + + "NEDAVNO KORIŠTENO" + "SMAJLIĆI I EMOCIJE" + "OSOBE" + "ŽIVOTINJE I PRIRODA" + "HRANA I PIĆE" + "PUTOVANJA I MJESTA" + "AKTIVNOSTI I DOGAĐAJI" + "OBJEKTI" + "SIMBOLI" + "ZASTAVE" + "Nije dostupan nijedan emoji" + "Još niste upotrijebili emojije" + "dvosmjerni izmjenjivač emojija" + "promijenjen je smjer emojija" + "alat za odabir varijante emojija" + "%1$s i %2$s" + "sjena" + "svijetla boja kože" + "srednje svijetla boja kože" + "srednja boja kože" + "srednje tamna boja kože" + "tamna boja kože" + diff --git a/emojipicker/app/src/main/res/values-hu/strings.xml b/emojipicker/app/src/main/res/values-hu/strings.xml new file mode 100644 index 000000000..d048746c7 --- /dev/null +++ b/emojipicker/app/src/main/res/values-hu/strings.xml @@ -0,0 +1,42 @@ + + + + + "LEGUTÓBB HASZNÁLT" + "HANGULATJELEK ÉS HANGULATOK" + "SZEMÉLYEK" + "ÁLLATOK ÉS TERMÉSZET" + "ÉTEL ÉS ITAL" + "UTAZÁS ÉS HELYEK" + "TEVÉKENYSÉGEK ÉS ESEMÉNYEK" + "TÁRGYAK" + "SZIMBÓLUMOK" + "ZÁSZLÓK" + "Nincsenek rendelkezésre álló emojik" + "Még nem használt emojikat" + "kétirányú emojiváltó" + "módosítva lett, hogy merre nézzen az emoji" + "emojiváltozat-választó" + "%1$s és %2$s" + "árnyék" + "világos bőrtónus" + "közepesen világos bőrtónus" + "közepes bőrtónus" + "közepesen sötét bőrtónus" + "sötét bőrtónus" + diff --git a/emojipicker/app/src/main/res/values-hy/strings.xml b/emojipicker/app/src/main/res/values-hy/strings.xml new file mode 100644 index 000000000..be551decf --- /dev/null +++ b/emojipicker/app/src/main/res/values-hy/strings.xml @@ -0,0 +1,42 @@ + + + + + "ՎԵՐՋԵՐՍ ՕԳՏԱԳՈՐԾՎԱԾ" + "ԶՄԱՅԼԻԿՆԵՐ ԵՎ ՀՈՒԶԱՊԱՏԿԵՐԱԿՆԵՐ" + "ՄԱՐԴԻԿ" + "ԿԵՆԴԱՆԻՆԵՐ ԵՎ ԲՆՈՒԹՅՈՒՆ" + "ՍՆՈՒՆԴ ԵՎ ԽՄԻՉՔ" + "ՃԱՄՓՈՐԴՈՒԹՅՈՒՆ ԵՎ ՏԵՍԱՐԺԱՆ ՎԱՅՐԵՐ" + "ԺԱՄԱՆՑ ԵՎ ՄԻՋՈՑԱՌՈՒՄՆԵՐ" + "ԱՌԱՐԿԱՆԵՐ" + "ՆՇԱՆՆԵՐ" + "ԴՐՈՇՆԵՐ" + "Հասանելի էմոջիներ չկան" + "Դուք դեռ չեք օգտագործել էմոջիներ" + "էմոջիների երկկողմանի փոխանջատիչ" + "էմոջիի դեմքի ուղղությունը փոխվեց" + "էմոջիների տարբերակի ընտրիչ" + "%1$s և %2$s" + "ստվեր" + "մաշկի բաց երանգ" + "մաշկի չափավոր բաց երանգ" + "մաշկի չեզոք երանգ" + "մաշկի չափավոր մուգ երանգ" + "մաշկի մուգ երանգ" + diff --git a/emojipicker/app/src/main/res/values-in/strings.xml b/emojipicker/app/src/main/res/values-in/strings.xml new file mode 100644 index 000000000..09703b727 --- /dev/null +++ b/emojipicker/app/src/main/res/values-in/strings.xml @@ -0,0 +1,42 @@ + + + + + "TERAKHIR DIGUNAKAN" + "SMILEY DAN EMOTIKON" + "ORANG" + "HEWAN DAN ALAM" + "MAKANAN DAN MINUMAN" + "WISATA DAN TEMPAT" + "AKTIVITAS DAN ACARA" + "OBJEK" + "SIMBOL" + "BENDERA" + "Tidak ada emoji yang tersedia" + "Anda belum menggunakan emoji apa pun" + "pengalih dua arah emoji" + "arah hadap emoji dialihkan" + "pemilih varian emoji" + "%1$s dan %2$s" + "bayangan" + "warna kulit cerah" + "warna kulit kuning langsat" + "warna kulit sawo matang" + "warna kulit cokelat" + "warna kulit gelap" + diff --git a/emojipicker/app/src/main/res/values-is/strings.xml b/emojipicker/app/src/main/res/values-is/strings.xml new file mode 100644 index 000000000..691d3c623 --- /dev/null +++ b/emojipicker/app/src/main/res/values-is/strings.xml @@ -0,0 +1,42 @@ + + + + + "NOTAÐ NÝLEGA" + "BROSKARLAR OG TILFINNINGAR" + "FÓLK" + "DÝR OG NÁTTÚRA" + "MATUR OG DRYKKUR" + "FERÐALÖG OG STAÐIR" + "VIRKNI OG VIÐBURÐIR" + "HLUTIR" + "TÁKN" + "FÁNAR" + "Engin emoji-tákn í boði" + "Þú hefur ekki notað nein emoji enn" + "emoji-val í báðar áttir" + "Áttinni sem emoji snýr að hefur verið breytt" + "val emoji-afbrigðis" + "%1$s og %2$s" + "skuggi" + "ljós húðlitur" + "meðalljós húðlitur" + "húðlitur í meðallagi" + "meðaldökkur húðlitur" + "dökkur húðlitur" + diff --git a/emojipicker/app/src/main/res/values-it/strings.xml b/emojipicker/app/src/main/res/values-it/strings.xml new file mode 100644 index 000000000..6ff2bf9c2 --- /dev/null +++ b/emojipicker/app/src/main/res/values-it/strings.xml @@ -0,0 +1,42 @@ + + + + + "USATE DI RECENTE" + "SMILE ED EMOZIONI" + "PERSONE" + "ANIMALI E NATURA" + "CIBO E BEVANDE" + "VIAGGI E LUOGHI" + "ATTIVITÀ ED EVENTI" + "OGGETTI" + "SIMBOLI" + "BANDIERE" + "Nessuna emoji disponibile" + "Non hai ancora usato alcuna emoji" + "selettore bidirezionale di emoji" + "emoji sottosopra" + "selettore variante emoji" + "%1$s e %2$s" + "ombra" + "carnagione chiara" + "carnagione medio-chiara" + "carnagione media" + "carnagione medio-scura" + "carnagione scura" + diff --git a/emojipicker/app/src/main/res/values-iw/strings.xml b/emojipicker/app/src/main/res/values-iw/strings.xml new file mode 100644 index 000000000..7a8eae8a7 --- /dev/null +++ b/emojipicker/app/src/main/res/values-iw/strings.xml @@ -0,0 +1,42 @@ + + + + + "בשימוש לאחרונה" + "סמיילי ואמוטיקונים" + "אנשים" + "בעלי חיים וטבע" + "מזון ומשקאות" + "נסיעות ומקומות" + "פעילויות ואירועים" + "אובייקטים" + "סמלים" + "דגלים" + "אין סמלי אמוג\'י זמינים" + "עדיין לא השתמשת באף אמוג\'י" + "לחצן דו-כיווני למעבר לאמוג\'י" + "מתג נגישות להחלפת הכיוון של האמוג\'י" + "בורר של סוגי אמוג\'י" + "‏%1$s ו-%2$s" + "צל" + "גוון עור בהיר" + "גוון עור בינוני-בהיר" + "גוון עור בינוני" + "גוון עור בינוני-כהה" + "גוון עור כהה" + diff --git a/emojipicker/app/src/main/res/values-ja/strings.xml b/emojipicker/app/src/main/res/values-ja/strings.xml new file mode 100644 index 000000000..395ee6d73 --- /dev/null +++ b/emojipicker/app/src/main/res/values-ja/strings.xml @@ -0,0 +1,42 @@ + + + + + "最近使用した絵文字" + "顔文字、気分" + "人物" + "動物、自然" + "食べ物、飲み物" + "移動、場所" + "活動、イベント" + "アイテム" + "記号" + "旗" + "使用できる絵文字がありません" + "まだ絵文字を使用していません" + "絵文字の双方向切り替え" + "絵文字の向きを切り替えました" + "絵文字バリエーション セレクタ" + "%1$s、%2$s" + "シャドウ" + "明るい肌の色" + "やや明るい肌の色" + "中間の明るさの肌の色" + "やや濃い肌の色" + "濃い肌の色" + diff --git a/emojipicker/app/src/main/res/values-ka/strings.xml b/emojipicker/app/src/main/res/values-ka/strings.xml new file mode 100644 index 000000000..5d23faa22 --- /dev/null +++ b/emojipicker/app/src/main/res/values-ka/strings.xml @@ -0,0 +1,42 @@ + + + + + "ბოლო დროს გამოყენებული" + "სიცილაკები და ემოციები" + "ადამიანები" + "ცხოველები და ბუნება" + "საჭმელი და სასმელი" + "მოგზაურობა და ადგილები" + "აქტივობები და მოვლენები" + "ობიექტები" + "სიმბოლოები" + "დროშები" + "Emoji-ები მიუწვდომელია" + "Emoji-ებით ჯერ არ გისარგებლიათ" + "emoji-ს ორმიმართულებიანი გადამრთველი" + "emoji-ის მიმართულება შეცვლილია" + "emoji-ს ვარიანტის ამომრჩევი" + "%1$s და %2$s" + "ჩრდილი" + "კანის ღია ტონი" + "კანის ღია საშუალო ტონი" + "კანის საშუალო ტონი" + "კანის მუქი საშუალო ტონი" + "კანის მუქი ტონი" + diff --git a/emojipicker/app/src/main/res/values-kk/strings.xml b/emojipicker/app/src/main/res/values-kk/strings.xml new file mode 100644 index 000000000..cd6a8c571 --- /dev/null +++ b/emojipicker/app/src/main/res/values-kk/strings.xml @@ -0,0 +1,42 @@ + + + + + "СОҢҒЫ ҚОЛДАНЫЛҒАНДАР" + "СМАЙЛДАР МЕН ЭМОЦИЯЛАР" + "АДАМДАР" + "ЖАНУАРЛАР ЖӘНЕ ТАБИҒАТ" + "ТАМАҚ ПЕН СУСЫН" + "САЯХАТ ЖӘНЕ ОРЫНДАР" + "ӘРЕКЕТТЕР МЕН ІС-ШАРАЛАР" + "НЫСАНДАР" + "ТАҢБАЛАР" + "ЖАЛАУШАЛАР" + "Эмоджи жоқ" + "Әлі ешқандай эмоджи пайдаланылған жоқ." + "екіжақты эмоджи ауыстырғыш" + "эмоджи бағыты ауыстырылды" + "эмоджи нұсқаларын таңдау құралы" + "%1$s және %2$s" + "көлеңке" + "терінің ақшыл реңі" + "терінің орташа ақшыл реңі" + "терінің орташа реңі" + "терінің орташа қараторы реңі" + "терінің қараторы реңі" + diff --git a/emojipicker/app/src/main/res/values-km/strings.xml b/emojipicker/app/src/main/res/values-km/strings.xml new file mode 100644 index 000000000..0b4dffc20 --- /dev/null +++ b/emojipicker/app/src/main/res/values-km/strings.xml @@ -0,0 +1,42 @@ + + + + + "បាន​ប្រើ​ថ្មីៗ​នេះ" + "រូប​ទឹក​មុខ និងអារម្មណ៍" + "មនុស្ស" + "សត្វ និងធម្មជាតិ" + "អាហារ និងភេសជ្ជៈ" + "ការធ្វើដំណើរ និងទីកន្លែង" + "សកម្មភាព និងព្រឹត្តិការណ៍" + "វត្ថុ" + "និមិត្តសញ្ញា" + "ទង់" + "មិនមាន​រូប​អារម្មណ៍ទេ" + "អ្នក​មិនទាន់​បានប្រើរូប​អារម្មណ៍​ណាមួយ​នៅឡើយទេ" + "មុខងារប្ដូរទ្វេទិសនៃរូប​អារម្មណ៍" + "បានប្ដូរទិសដៅបែររបស់រូប​អារម្មណ៍" + "ផ្ទាំងជ្រើសរើសជម្រើសរូប​អារម្មណ៍" + "%1$s និង %2$s" + "ស្រមោល" + "សម្បុរស្បែក​ស" + "សម្បុរស្បែក​សល្មម" + "សម្បុរ​ស្បែក​ល្មម" + "សម្បុរ​ស្បែកខ្មៅល្មម" + "សម្បុរ​ស្បែក​ខ្មៅ" + diff --git a/emojipicker/app/src/main/res/values-kn/strings.xml b/emojipicker/app/src/main/res/values-kn/strings.xml new file mode 100644 index 000000000..b05a64c2c --- /dev/null +++ b/emojipicker/app/src/main/res/values-kn/strings.xml @@ -0,0 +1,42 @@ + + + + + "ಇತ್ತೀಚೆಗೆ ಬಳಸಿರುವುದು" + "ಸ್ಮೈಲಿಗಳು ಮತ್ತು ಭಾವನೆಗಳು" + "ಜನರು" + "ಪ್ರಾಣಿಗಳು ಮತ್ತು ಪ್ರಕೃತಿ" + "ಆಹಾರ ಮತ್ತು ಪಾನೀಯ" + "ಪ್ರಯಾಣ ಮತ್ತು ಸ್ಥಳಗಳು" + "ಚಟುವಟಿಕೆಗಳು ಮತ್ತು ಈವೆಂಟ್‌ಗಳು" + "ವಸ್ತುಗಳು" + "ಸಂಕೇತಗಳು" + "ಫ್ಲ್ಯಾಗ್‌ಗಳು" + "ಯಾವುದೇ ಎಮೊಜಿಗಳು ಲಭ್ಯವಿಲ್ಲ" + "ನೀವು ಇನ್ನೂ ಯಾವುದೇ ಎಮೋಜಿಗಳನ್ನು ಬಳಸಿಲ್ಲ" + "ಎಮೋಜಿ ಬೈಡೈರೆಕ್ಷನಲ್ ಸ್ವಿಚರ್" + "ಎಮೋಜಿ ಎದುರಿಸುತ್ತಿರುವ ದಿಕ್ಕನ್ನು ಬದಲಾಯಿಸಲಾಗಿದೆ" + "ಎಮೋಜಿ ವೇರಿಯಂಟ್ ಸೆಲೆಕ್ಟರ್" + "%1$s ಮತ್ತು %2$s" + "ನೆರಳು" + "ಲೈಟ್ ಸ್ಕಿನ್ ಟೋನ್" + "ಮೀಡಿಯಮ್ ಲೈಟ್ ಸ್ಕಿನ್ ಟೋನ್" + "ಮೀಡಿಯಮ್ ಸ್ಕಿನ್ ಟೋನ್" + "ಮೀಡಿಯಮ್ ಡಾರ್ಕ್ ಸ್ಕಿನ್ ಟೋನ್" + "ಡಾರ್ಕ್ ಸ್ಕಿನ್ ಟೋನ್" + diff --git a/emojipicker/app/src/main/res/values-ko/strings.xml b/emojipicker/app/src/main/res/values-ko/strings.xml new file mode 100644 index 000000000..22cace838 --- /dev/null +++ b/emojipicker/app/src/main/res/values-ko/strings.xml @@ -0,0 +1,42 @@ + + + + + "최근 사용" + "이모티콘 및 감정" + "사람" + "동물 및 자연" + "식음료" + "여행 및 장소" + "활동 및 이벤트" + "사물" + "기호" + "깃발" + "사용 가능한 그림 이모티콘 없음" + "아직 사용한 이모티콘이 없습니다." + "그림 이모티콘 양방향 전환기" + "이모티콘 방향 전환됨" + "그림 이모티콘 옵션 선택기" + "%1$s 및 %2$s" + "그림자" + "밝은 피부색" + "약간 밝은 피부색" + "중간 피부색" + "약간 어두운 피부색" + "어두운 피부색" + diff --git a/emojipicker/app/src/main/res/values-ky/strings.xml b/emojipicker/app/src/main/res/values-ky/strings.xml new file mode 100644 index 000000000..aa3454690 --- /dev/null +++ b/emojipicker/app/src/main/res/values-ky/strings.xml @@ -0,0 +1,42 @@ + + + + + "АКЫРКЫ КОЛДОНУЛГАНДАР" + "БЫЙТЫКЧАЛАР ЖАНА ЭМОЦИЯЛАР" + "АДАМДАР" + "ЖАНЫБАРЛАР ЖАНА ЖАРАТЫЛЫШ" + "АЗЫК-ТҮЛҮК ЖАНА СУУСУНДУКТАР" + "САЯКАТ ЖАНА ЖЕРЛЕР" + "ИШ-АРАКЕТТЕР ЖАНА ИШ-ЧАРАЛАР" + "ОБЪЕКТТЕР" + "СИМВОЛДОР" + "ЖЕЛЕКТЕР" + "Жеткиликтүү быйтыкчалар жок" + "Бир да быйтыкча колдоно элексиз" + "эки тараптуу быйтыкча которгуч" + "быйтыкчанын багыты которулду" + "быйтыкча тандагыч" + "%1$s жана %2$s" + "көлөкө" + "ачык түстүү тери" + "агыраак түстүү тери" + "орточо түстүү тери" + "орточо кара тору түстүү тери" + "кара тору түстүү тери" + diff --git a/emojipicker/app/src/main/res/values-lo/strings.xml b/emojipicker/app/src/main/res/values-lo/strings.xml new file mode 100644 index 000000000..174400e08 --- /dev/null +++ b/emojipicker/app/src/main/res/values-lo/strings.xml @@ -0,0 +1,42 @@ + + + + + "ໃຊ້ຫຼ້າສຸດ" + "ໜ້າຍິ້ມ ແລະ ຄວາມຮູ້ສຶກ" + "ຜູ້ຄົນ" + "ສັດ ແລະ ທຳມະຊາດ" + "ອາຫານ ແລະ ເຄື່ອງດື່ມ" + "ການເດີນທາງ ແລະ ສະຖານທີ່" + "ການເຄື່ອນໄຫວ ແລະ ກິດຈະກຳ" + "ວັດຖຸ" + "ສັນຍາລັກ" + "ທຸງ" + "ບໍ່ມີອີໂມຈິໃຫ້ນຳໃຊ້" + "ທ່ານຍັງບໍ່ໄດ້ໃຊ້ອີໂມຈິໃດເທື່ອ" + "ຕົວສະຫຼັບອີໂມຈິແບບ 2 ທິດທາງ" + "ປ່ຽນທິດທາງການຫັນໜ້າຂອງອີໂມຈິແລ້ວ" + "ຕົວເລືອກຕົວແປອີໂມຈິ" + "%1$s ແລະ %2$s" + "ເງົາ" + "ສະກິນໂທນແຈ້ງ" + "ສະກິນໂທນແຈ້ງປານກາງ" + "ສະກິນໂທນປານກາງ" + "ສະກິນໂທນມືດປານກາງ" + "ສະກິນໂທນມືດ" + diff --git a/emojipicker/app/src/main/res/values-lt/strings.xml b/emojipicker/app/src/main/res/values-lt/strings.xml new file mode 100644 index 000000000..72390ae43 --- /dev/null +++ b/emojipicker/app/src/main/res/values-lt/strings.xml @@ -0,0 +1,42 @@ + + + + + "NESENIAI NAUDOTI" + "JAUSTUKAI IR EMOCIJOS" + "ŽMONĖS" + "GYVŪNAI IR GAMTA" + "MAISTAS IR GĖRIMAI" + "KELIONĖS IR VIETOS" + "VEIKLA IR ĮVYKIAI" + "OBJEKTAI" + "SIMBOLIAI" + "VĖLIAVOS" + "Nėra jokių pasiekiamų jaustukų" + "Dar nenaudojote jokių jaustukų" + "dvikryptis jaustukų perjungikli" + "perjungta jaustukų nuoroda" + "jaustuko varianto parinkiklis" + "%1$s ir %2$s" + "šešėlis" + "šviesi odos spalva" + "vidutiniškai šviesi odos spalva" + "nei tamsi, nei šviesi odos spalva" + "vidutiniškai tamsi odos spalva" + "tamsi odos spalva" + diff --git a/emojipicker/app/src/main/res/values-lv/strings.xml b/emojipicker/app/src/main/res/values-lv/strings.xml new file mode 100644 index 000000000..0fe66ac75 --- /dev/null +++ b/emojipicker/app/src/main/res/values-lv/strings.xml @@ -0,0 +1,42 @@ + + + + + "NESEN LIETOTAS" + "SMAIDIŅI UN EMOCIJAS" + "PERSONAS" + "DZĪVNIEKI UN DABA" + "ĒDIENI UN DZĒRIENI" + "CEĻOJUMI UN VIETAS" + "PASĀKUMI UN NOTIKUMI" + "OBJEKTI" + "SIMBOLI" + "KAROGI" + "Nav pieejamu emocijzīmju" + "Jūs vēl neesat izmantojis nevienu emocijzīmi" + "emocijzīmju divvirzienu pārslēdzējs" + "mainīts emocijzīmes virziens" + "emocijzīmes varianta atlasītājs" + "%1$s un %2$s" + "ēna" + "gaišs ādas tonis" + "vidēji gaišs ādas tonis" + "vidējs ādas tonis" + "vidēji tumšs ādas tonis" + "tumšs ādas tonis" + diff --git a/emojipicker/app/src/main/res/values-mk/strings.xml b/emojipicker/app/src/main/res/values-mk/strings.xml new file mode 100644 index 000000000..b7ceab0f4 --- /dev/null +++ b/emojipicker/app/src/main/res/values-mk/strings.xml @@ -0,0 +1,42 @@ + + + + + "НЕОДАМНА КОРИСТЕНИ" + "СМЕШКОВЦИ И ЕМОЦИИ" + "ЛУЃЕ" + "ЖИВОТНИ И ПРИРОДА" + "ХРАНА И ПИЈАЛАЦИ" + "ПАТУВАЊЕ И МЕСТА" + "АКТИВНОСТИ И НАСТАНИ" + "ОБЈЕКТИ" + "СИМБОЛИ" + "ЗНАМИЊА" + "Нема достапни емоџија" + "Сѐ уште не сте користеле емоџија" + "двонасочен менувач на емоџија" + "насоката во којашто е свртено емоџито е сменета" + "избирач на варијанти на емоџија" + "%1$s и %2$s" + "сенка" + "светол тон на кожата" + "средно светол тон на кожата" + "среден тон на кожата" + "средно темен тон на кожата" + "темен тон на кожата" + diff --git a/emojipicker/app/src/main/res/values-ml/strings.xml b/emojipicker/app/src/main/res/values-ml/strings.xml new file mode 100644 index 000000000..60b985701 --- /dev/null +++ b/emojipicker/app/src/main/res/values-ml/strings.xml @@ -0,0 +1,42 @@ + + + + + "അടുത്തിടെ ഉപയോഗിച്ചവ" + "സ്മൈലികളും ഇമോഷനുകളും" + "ആളുകൾ" + "മൃഗങ്ങളും പ്രകൃതിയും" + "ഭക്ഷണപാനീയങ്ങൾ" + "യാത്രയും സ്ഥലങ്ങളും" + "ആക്‌റ്റിവിറ്റികളും ഇവന്റുകളും" + "വസ്‌തുക്കൾ" + "ചിഹ്നങ്ങൾ" + "പതാകകൾ" + "ഇമോജികളൊന്നും ലഭ്യമല്ല" + "നിങ്ങൾ ഇതുവരെ ഇമോജികളൊന്നും ഉപയോഗിച്ചിട്ടില്ല" + "ഇമോജി ദ്വിദിശ സ്വിച്ചർ" + "ഇമോജിയുടെ ദിശ മാറ്റി" + "ഇമോജി വേരിയന്റ് സെലക്‌ടർ" + "%1$s, %2$s" + "ഷാഡോ" + "ലൈറ്റ് സ്‌കിൻ ടോൺ" + "മീഡിയം ലൈറ്റ് സ്‌കിൻ ടോൺ" + "മീഡിയം സ്‌കിൻ ടോൺ" + "മീഡിയം ഡാർക്ക് സ്‌കിൻ ടോൺ" + "ഡാർക്ക് സ്‌കിൻ ടോൺ" + diff --git a/emojipicker/app/src/main/res/values-mn/strings.xml b/emojipicker/app/src/main/res/values-mn/strings.xml new file mode 100644 index 000000000..6b07ea5ae --- /dev/null +++ b/emojipicker/app/src/main/res/values-mn/strings.xml @@ -0,0 +1,42 @@ + + + + + "САЯХАН АШИГЛАСАН" + "ИНЭЭМСЭГЛЭЛ БОЛОН СЭТГЭЛ ХӨДЛӨЛ" + "ХҮМҮҮС" + "АМЬТАД БА БАЙГАЛЬ" + "ХООЛ БОЛОН УУХ ЗҮЙЛ" + "АЯЛАЛ БОЛОН ГАЗРУУД" + "ҮЙЛ АЖИЛЛАГАА БОЛОН АРГА ХЭМЖЭЭ" + "ОБЪЕКТ" + "ТЭМДЭГ" + "ТУГ" + "Боломжтой эможи алга" + "Та ямар нэгэн эможи ашиглаагүй байна" + "эможигийн хоёр чиглэлтэй сэлгүүр" + "эможигийн харж буй чиглэлийг сэлгэсэн" + "эможигийн хувилбар сонгогч" + "%1$s болон %2$s" + "сүүдэр" + "цайвар арьсны өнгө" + "дунд зэргийн цайвар арьсны өнгө" + "дунд зэргийн арьсны өнгө" + "дунд зэргийн бараан арьсны өнгө" + "бараан арьсны өнгө" + diff --git a/emojipicker/app/src/main/res/values-mr/strings.xml b/emojipicker/app/src/main/res/values-mr/strings.xml new file mode 100644 index 000000000..316b2c485 --- /dev/null +++ b/emojipicker/app/src/main/res/values-mr/strings.xml @@ -0,0 +1,42 @@ + + + + + "अलीकडे वापरलेला" + "स्मायली आणि भावना" + "लोक" + "प्राणी आणि निसर्ग" + "खाद्यपदार्थ आणि पेय" + "प्रवास आणि ठिकाणे" + "ॲक्टिव्हिटी आणि इव्हेंट" + "ऑब्जेक्ट" + "चिन्हे" + "ध्वज" + "कोणतेही इमोजी उपलब्ध नाहीत" + "तुम्ही अद्याप कोणतेही इमोजी वापरलेले नाहीत" + "इमोजीचा द्विदिश स्विचर" + "दिशा दाखवणारा इमोजी स्विच केला" + "इमोजी व्हेरीयंट सिलेक्टर" + "%1$s आणि %2$s" + "शॅडो" + "उजळ रंगाची त्वचा" + "मध्यम उजळ रंगाची त्वचा" + "मध्यम रंगाची त्वचा" + "मध्यम गडद रंगाची त्वचा" + "गडद रंगाची त्वचा" + diff --git a/emojipicker/app/src/main/res/values-ms/strings.xml b/emojipicker/app/src/main/res/values-ms/strings.xml new file mode 100644 index 000000000..d5ecef2db --- /dev/null +++ b/emojipicker/app/src/main/res/values-ms/strings.xml @@ -0,0 +1,42 @@ + + + + + "DIGUNAKAN BARU-BARU INI" + "SMILEY DAN EMOSI" + "ORANG" + "HAIWAN DAN ALAM SEMULA JADI" + "MAKANAN DAN MINUMAN" + "PERJALANAN DAN TEMPAT" + "AKTIVITI DAN ACARA" + "OBJEK" + "SIMBOL" + "BENDERA" + "Tiada emoji tersedia" + "Anda belum menggunakan mana-mana emoji lagi" + "penukar dwiarah emoji" + "emoji menghadap arah ditukar" + "pemilih varian emoji" + "%1$s dan %2$s" + "bebayang" + "ton kulit cerah" + "ton kulit sederhana cerah" + "ton kulit sederhana" + "ton kulit sederhana gelap" + "ton kulit gelap" + diff --git a/emojipicker/app/src/main/res/values-my/strings.xml b/emojipicker/app/src/main/res/values-my/strings.xml new file mode 100644 index 000000000..99fb7ff2a --- /dev/null +++ b/emojipicker/app/src/main/res/values-my/strings.xml @@ -0,0 +1,42 @@ + + + + + "မကြာသေးမီက သုံးထားသည်များ" + "စမိုင်းလီနှင့် ခံစားချက်များ" + "လူများ" + "တိရစ္ဆာန်များနှင့် သဘာဝ" + "အစားအသောက်" + "ခရီးသွားခြင်းနှင့် အရပ်ဒေသများ" + "လုပ်ဆောင်ချက်နှင့် အစီအစဉ်များ" + "အရာဝတ္ထုများ" + "သင်္ကေတများ" + "အလံများ" + "အီမိုဂျီ မရနိုင်ပါ" + "အီမိုဂျီ အသုံးမပြုသေးပါ" + "အီမိုဂျီ လမ်းကြောင်းနှစ်ခုပြောင်းစနစ်" + "အီမိုဂျီလှည့်သောဘက်ကို ပြောင်းထားသည်" + "အီမိုဂျီမူကွဲ ရွေးချယ်စနစ်" + "%1$s နှင့် %2$s" + "အရိပ်" + "ဖြူသည့် အသားအရောင်" + "အနည်းငယ်ဖြူသည့် အသားအရောင်" + "အလယ်အလတ် အသားအရောင်" + "အနည်းငယ်ညိုသည့် အသားအရောင်" + "ညိုသည့် အသားအရောင်" + diff --git a/emojipicker/app/src/main/res/values-nb/strings.xml b/emojipicker/app/src/main/res/values-nb/strings.xml new file mode 100644 index 000000000..368ef416b --- /dev/null +++ b/emojipicker/app/src/main/res/values-nb/strings.xml @@ -0,0 +1,42 @@ + + + + + "NYLIG BRUKT" + "SMILEFJES OG UTTRYKKSIKONER" + "PERSONER" + "DYR OG NATUR" + "MAT OG DRIKKE" + "REISE OG STEDER" + "AKTIVITETER OG ARRANGEMENTER" + "GJENSTANDER" + "SYMBOLER" + "FLAGG" + "Ingen emojier er tilgjengelige" + "Du har ikke brukt noen emojier ennå" + "toveisvelger for emoji" + "emojiretningen er slått på" + "velger for emojivariant" + "%1$s og %2$s" + "skygge" + "lys hudtone" + "middels lys hudtone" + "middels hudtone" + "middels mørk hudtone" + "mørk hudtone" + diff --git a/emojipicker/app/src/main/res/values-ne/strings.xml b/emojipicker/app/src/main/res/values-ne/strings.xml new file mode 100644 index 000000000..50a489be6 --- /dev/null +++ b/emojipicker/app/src/main/res/values-ne/strings.xml @@ -0,0 +1,42 @@ + + + + + "हालसालै प्रयोग गरिएको" + "स्माइली र भावनाहरू" + "मान्छेहरू" + "पशु र प्रकृति" + "खाद्य तथा पेय पदार्थ" + "यात्रा र ठाउँहरू" + "क्रियाकलाप तथा कार्यक्रमहरू" + "वस्तुहरू" + "चिन्हहरू" + "झन्डाहरू" + "कुनै पनि इमोजी उपलब्ध छैन" + "तपाईंले हालसम्म कुनै पनि इमोजी प्रयोग गर्नुभएको छैन" + "दुवै दिशामा लैजान सकिने स्विचरको इमोजी" + "इमोजी फर्केको दिशा बदलियो" + "इमोजी भेरियन्ट सेलेक्टर" + "%1$s र %2$s" + "छाया" + "छालाको फिक्का रङ" + "छालाको मध्यम फिक्का रङ" + "छालाको मध्यम रङ" + "छालाको मध्यम गाढा रङ" + "छालाको गाढा रङ" + diff --git a/emojipicker/app/src/main/res/values-nl/strings.xml b/emojipicker/app/src/main/res/values-nl/strings.xml new file mode 100644 index 000000000..12d8b4054 --- /dev/null +++ b/emojipicker/app/src/main/res/values-nl/strings.xml @@ -0,0 +1,42 @@ + + + + + "ONLANGS GEBRUIKT" + "SMILEYS EN EMOTIES" + "MENSEN" + "DIEREN EN NATUUR" + "ETEN EN DRINKEN" + "REIZEN EN PLAATSEN" + "ACTIVITEITEN EN EVENEMENTEN" + "OBJECTEN" + "SYMBOLEN" + "VLAGGEN" + "Geen emoji\'s beschikbaar" + "Je hebt nog geen emoji\'s gebruikt" + "bidirectionele emoji-schakelaar" + "richting van emoji omgewisseld" + "emoji-variantkiezer" + "%1$s en %2$s" + "schaduw" + "lichte huidskleur" + "middellichte huidskleur" + "medium huidskleur" + "middeldonkere huidskleur" + "donkere huidskleur" + diff --git a/emojipicker/app/src/main/res/values-or/strings.xml b/emojipicker/app/src/main/res/values-or/strings.xml new file mode 100644 index 000000000..30ffd391f --- /dev/null +++ b/emojipicker/app/src/main/res/values-or/strings.xml @@ -0,0 +1,42 @@ + + + + + "ବର୍ତ୍ତମାନ ବ୍ୟବହାର କରାଯାଇଛି" + "ସ୍ମାଇଲି ଓ ଆବେଗଗୁଡ଼ିକ" + "ଲୋକମାନେ" + "ଜୀବଜନ୍ତୁ ଓ ପ୍ରକୃତି" + "ଖାଦ୍ୟ ଓ ପାନୀୟ" + "ଟ୍ରାଭେଲ ଓ ସ୍ଥାନଗୁଡ଼ିକ" + "କାର୍ଯ୍ୟକଳାପ ଓ ଇଭେଣ୍ଟଗୁଡ଼ିକ" + "ଅବଜେକ୍ଟଗୁଡ଼ିକ" + "ଚିହ୍ନଗୁଡ଼ିକ" + "ଫ୍ଲାଗଗୁଡ଼ିକ" + "କୌଣସି ଇମୋଜି ଉପଲବ୍ଧ ନାହିଁ" + "ଆପଣ ଏପର୍ଯ୍ୟନ୍ତ କୌଣସି ଇମୋଜି ବ୍ୟବହାର କରିନାହାଁନ୍ତି" + "ଇମୋଜିର ବାଇଡାଇରେକ୍ସନାଲ ସୁଇଚର" + "ଇମୋଜି ଫେସିଂ ଦିଗନିର୍ଦ୍ଦେଶ ସୁଇଚ କରାଯାଇଛି" + "ଇମୋଜି ଭାରିଏଣ୍ଟ ଚୟନକାରୀ" + "%1$s ଏବଂ %2$s" + "ସେଡୋ" + "ଲାଇଟ ସ୍କିନ ଟୋନ" + "ମଧ୍ୟମ ଲାଇଟ ସ୍କିନ ଟୋନ" + "ମଧ୍ୟମ ସ୍କିନ ଟୋନ" + "ମଧ୍ୟମ ଡାର୍କ ସ୍କିନ ଟୋନ" + "ଡାର୍କ ସ୍କିନ ଟୋନ" + diff --git a/emojipicker/app/src/main/res/values-pa/strings.xml b/emojipicker/app/src/main/res/values-pa/strings.xml new file mode 100644 index 000000000..85db6c7f4 --- /dev/null +++ b/emojipicker/app/src/main/res/values-pa/strings.xml @@ -0,0 +1,42 @@ + + + + + "ਹਾਲ ਹੀ ਵਿੱਚ ਵਰਤਿਆ ਗਿਆ" + "ਸਮਾਈਲੀ ਅਤੇ ਜਜ਼ਬਾਤ" + "ਲੋਕ" + "ਜਾਨਵਰ ਅਤੇ ਕੁਦਰਤ" + "ਖਾਣਾ ਅਤੇ ਪੀਣਾ" + "ਯਾਤਰਾ ਅਤੇ ਥਾਵਾਂ" + "ਸਰਗਰਮੀਆਂ ਅਤੇ ਇਵੈਂਟ" + "ਵਸਤੂਆਂ" + "ਚਿੰਨ੍ਹ" + "ਝੰਡੇ" + "ਕੋਈ ਇਮੋਜੀ ਉਪਲਬਧ ਨਹੀਂ ਹੈ" + "ਤੁਸੀਂ ਹਾਲੇ ਤੱਕ ਕਿਸੇ ਵੀ ਇਮੋਜੀ ਦੀ ਵਰਤੋਂ ਨਹੀਂ ਕੀਤੀ ਹੈ" + "ਇਮੋਜੀ ਬਾਇਡਾਇਰੈਕਸ਼ਨਲ ਸਵਿੱਚਰ" + "ਇਮੋਜੀ ਦੀ ਦਿਸ਼ਾ ਬਦਲ ਦਿੱਤੀ ਗਈ" + "ਇਮੋਜੀ ਕਿਸਮ ਚੋਣਕਾਰ" + "%1$s ਅਤੇ %2$s" + "ਸ਼ੈਡੋ" + "ਚਮੜੀ ਦਾ ਹਲਕਾ ਰੰਗ" + "ਚਮੜੀ ਦਾ ਦਰਮਿਆਨਾ ਹਲਕਾ ਰੰਗ" + "ਚਮੜੀ ਦਾ ਦਰਮਿਆਨਾ ਰੰਗ" + "ਚਮੜੀ ਦਾ ਦਰਮਿਆਨਾ ਗੂੜ੍ਹਾ ਰੰਗ" + "ਚਮੜੀ ਦਾ ਗੂੜ੍ਹਾ ਰੰਗ" + diff --git a/emojipicker/app/src/main/res/values-pl/strings.xml b/emojipicker/app/src/main/res/values-pl/strings.xml new file mode 100644 index 000000000..3ed8bd349 --- /dev/null +++ b/emojipicker/app/src/main/res/values-pl/strings.xml @@ -0,0 +1,42 @@ + + + + + "OSTATNIO UŻYWANE" + "EMOTIKONY" + "UCZESTNICY" + "ZWIERZĘTA I PRZYRODA" + "JEDZENIE I NAPOJE" + "PODRÓŻE I MIEJSCA" + "DZIAŁANIA I ZDARZENIA" + "PRZEDMIOTY" + "SYMBOLE" + "FLAGI" + "Brak dostępnych emotikonów" + "Żadne emotikony nie zostały jeszcze użyte" + "dwukierunkowy przełącznik emotikonów" + "zmieniono kierunek emotikonów" + "selektor wariantu emotikona" + "%1$s i %2$s" + "cień" + "jasny odcień skóry" + "średnio jasny odcień skóry" + "pośredni odcień skóry" + "średnio ciemny odcień skóry" + "ciemny odcień skóry" + diff --git a/emojipicker/app/src/main/res/values-pt-rBR/strings.xml b/emojipicker/app/src/main/res/values-pt-rBR/strings.xml new file mode 100644 index 000000000..5883fcb3c --- /dev/null +++ b/emojipicker/app/src/main/res/values-pt-rBR/strings.xml @@ -0,0 +1,42 @@ + + + + + "USADOS RECENTEMENTE" + "CARINHAS E EMOTICONS" + "PESSOAS" + "ANIMAIS E NATUREZA" + "COMIDAS E BEBIDAS" + "VIAGENS E LUGARES" + "ATIVIDADES E EVENTOS" + "OBJETOS" + "SÍMBOLOS" + "BANDEIRAS" + "Não há emojis disponíveis" + "Você ainda não usou emojis" + "seletor bidirecional de emojis" + "emoji virado para a direção trocada" + "seletor de variante do emoji" + "%1$s e %2$s" + "sombra" + "tom de pele claro" + "tom de pele médio-claro" + "tom de pele médio" + "tom de pele médio-escuro" + "tom de pele escuro" + diff --git a/emojipicker/app/src/main/res/values-pt-rPT/strings.xml b/emojipicker/app/src/main/res/values-pt-rPT/strings.xml new file mode 100644 index 000000000..2ef06acc4 --- /dev/null +++ b/emojipicker/app/src/main/res/values-pt-rPT/strings.xml @@ -0,0 +1,42 @@ + + + + + "USADOS RECENTEMENTE" + "EMOTICONS E ÍCONES EXPRESSIVOS" + "PESSOAS" + "ANIMAIS E NATUREZA" + "ALIMENTOS E BEBIDAS" + "VIAGENS E LOCAIS" + "ATIVIDADES E EVENTOS" + "OBJETOS" + "SÍMBOLOS" + "BANDEIRAS" + "Nenhum emoji disponível" + "Ainda não utilizou emojis" + "comutador bidirecional de emojis" + "direção voltada para o emoji alterada" + "seletor de variantes de emojis" + "%1$s e %2$s" + "sombra" + "tom de pele claro" + "tom de pele claro médio" + "tom de pele médio" + "tom de pele escuro médio" + "tom de pele escuro" + diff --git a/emojipicker/app/src/main/res/values-pt/strings.xml b/emojipicker/app/src/main/res/values-pt/strings.xml new file mode 100644 index 000000000..5883fcb3c --- /dev/null +++ b/emojipicker/app/src/main/res/values-pt/strings.xml @@ -0,0 +1,42 @@ + + + + + "USADOS RECENTEMENTE" + "CARINHAS E EMOTICONS" + "PESSOAS" + "ANIMAIS E NATUREZA" + "COMIDAS E BEBIDAS" + "VIAGENS E LUGARES" + "ATIVIDADES E EVENTOS" + "OBJETOS" + "SÍMBOLOS" + "BANDEIRAS" + "Não há emojis disponíveis" + "Você ainda não usou emojis" + "seletor bidirecional de emojis" + "emoji virado para a direção trocada" + "seletor de variante do emoji" + "%1$s e %2$s" + "sombra" + "tom de pele claro" + "tom de pele médio-claro" + "tom de pele médio" + "tom de pele médio-escuro" + "tom de pele escuro" + diff --git a/emojipicker/app/src/main/res/values-ro/strings.xml b/emojipicker/app/src/main/res/values-ro/strings.xml new file mode 100644 index 000000000..45fad5a7e --- /dev/null +++ b/emojipicker/app/src/main/res/values-ro/strings.xml @@ -0,0 +1,42 @@ + + + + + "FOLOSITE RECENT" + "EMOTICOANE ȘI EMOȚII" + "PERSOANE" + "ANIMALE ȘI NATURĂ" + "MÂNCARE ȘI BĂUTURĂ" + "CĂLĂTORII ȘI LOCAȚII" + "ACTIVITĂȚI ȘI EVENIMENTE" + "OBIECTE" + "SIMBOLURI" + "STEAGURI" + "Nu sunt disponibile emoji-uri" + "Încă nu ai folosit emoji" + "comutator bidirecțional de emojiuri" + "direcția de orientare a emojiului comutată" + "selector de variante de emoji" + "%1$s și %2$s" + "umbră" + "nuanță deschisă a pielii" + "nuanță deschisă medie a pielii" + "nuanță medie a pielii" + "nuanță închisă medie a pielii" + "nuanță închisă a pielii" + diff --git a/emojipicker/app/src/main/res/values-ru/strings.xml b/emojipicker/app/src/main/res/values-ru/strings.xml new file mode 100644 index 000000000..ecf42faa4 --- /dev/null +++ b/emojipicker/app/src/main/res/values-ru/strings.xml @@ -0,0 +1,42 @@ + + + + + "НЕДАВНИЕ" + "СМАЙЛИКИ И ЭМОЦИИ" + "ЛЮДИ" + "ПРИРОДА И ЖИВОТНЫЕ" + "ЕДА И НАПИТКИ" + "ПУТЕШЕСТВИЯ" + "ДЕЙСТВИЯ И СОБЫТИЯ" + "ОБЪЕКТЫ" + "СИМВОЛЫ" + "ФЛАГИ" + "Нет доступных эмодзи" + "Вы ещё не использовали эмодзи" + "Двухсторонний переключатель эмодзи" + "изменен поворот лица эмодзи" + "выбор вариантов эмодзи" + "%1$s и %2$s" + "теневой" + "светлый оттенок кожи" + "умеренно светлый оттенок кожи" + "нейтральный оттенок кожи" + "умеренно темный оттенок кожи" + "темный оттенок кожи" + diff --git a/emojipicker/app/src/main/res/values-si/strings.xml b/emojipicker/app/src/main/res/values-si/strings.xml new file mode 100644 index 000000000..2ecdc77b3 --- /dev/null +++ b/emojipicker/app/src/main/res/values-si/strings.xml @@ -0,0 +1,42 @@ + + + + + "මෑතදී භාවිත කළ" + "සිනාසීම් සහ චිත්තවේග" + "පුද්ගලයින්" + "සතුන් හා ස්වභාවධර්මය" + "ආහාර පාන" + "සංචාර හා ස්ථාන" + "ක්‍රියාකාරකම් සහ සිදුවීම්" + "වස්තු" + "සංකේත" + "ධජ" + "ඉමොජි කිසිවක් නොලැබේ" + "ඔබ තවමත් කිසිදු ඉමෝජියක් භාවිතා කර නැත" + "ද්විත්ව දිශා ඉමොජි මාරුකරණය" + "ඉමොජි මුහුණ දෙන දිශාව මාරු විය" + "ඉමොජි ප්‍රභේද තෝරකය" + "%1$s සහ %2$s" + "සෙවනැල්ල" + "ලා සමේ වර්ණය" + "මධ්‍යම ලා සම් වර්ණය" + "මධ්‍යම සම් වර්ණය" + "මධ්‍යම අඳුරු සම් වර්ණය" + "අඳුරු සම් වර්ණය" + diff --git a/emojipicker/app/src/main/res/values-sk/strings.xml b/emojipicker/app/src/main/res/values-sk/strings.xml new file mode 100644 index 000000000..11ed0eeaa --- /dev/null +++ b/emojipicker/app/src/main/res/values-sk/strings.xml @@ -0,0 +1,42 @@ + + + + + "NEDÁVNO POUŽITÉ" + "SMAJLÍKY A EMÓCIE" + "ĽUDIA" + "ZVIERATÁ A PRÍRODA" + "JEDLO A NÁPOJE" + "CESTOVANIE A MIESTA" + "AKTIVITY A UDALOSTI" + "PREDMETY" + "SYMBOLY" + "VLAJKY" + "Nie sú k dispozícii žiadne emodži" + "Zatiaľ ste nepoužili žiadne emodži" + "obojsmerný prepínač emodži" + "smer otočenia emodži bol prepnutý" + "selektor variantu emodži" + "%1$s a %2$s" + "tieň" + "svetlý odtieň pokožky" + "stredne svetlý odtieň pokožky" + "stredný odtieň pokožky" + "stredne tmavý odtieň pokožky" + "tmavý odtieň pokožky" + diff --git a/emojipicker/app/src/main/res/values-sl/strings.xml b/emojipicker/app/src/main/res/values-sl/strings.xml new file mode 100644 index 000000000..f345226d0 --- /dev/null +++ b/emojipicker/app/src/main/res/values-sl/strings.xml @@ -0,0 +1,42 @@ + + + + + "NEDAVNO UPORABLJENI" + "ČUSTVENI SIMBOLI IN ČUSTVA" + "OSEBE" + "ŽIVALI IN NARAVA" + "HRANA IN PIJAČA" + "POTOVANJE IN MESTA" + "DEJAVNOSTI IN DOGODKI" + "PREDMETI" + "SIMBOLI" + "ZASTAVE" + "Ni emodžijev" + "Uporabili niste še nobenega emodžija." + "dvosmerni preklopnik emodžijev" + "preklopljena usmerjenost emodžija" + "Izbirnik različice emodžija" + "%1$s in %2$s" + "senčenje" + "svetel odtenek kože" + "srednje svetel odtenek kože" + "srednji odtenek kože" + "srednje temen odtenek kože" + "temen odtenek kože" + diff --git a/emojipicker/app/src/main/res/values-sq/strings.xml b/emojipicker/app/src/main/res/values-sq/strings.xml new file mode 100644 index 000000000..f30f751ef --- /dev/null +++ b/emojipicker/app/src/main/res/values-sq/strings.xml @@ -0,0 +1,42 @@ + + + + + "PËRDORUR SË FUNDI" + "BUZËQESHJE DHE EMOCIONE" + "NJERËZ" + "KAFSHË DHE NATYRË" + "USHQIME DHE PIJE" + "UDHËTIME DHE VENDE" + "AKTIVITETE DHE NGJARJE" + "OBJEKTE" + "SIMBOLE" + "FLAMUJ" + "Nuk ofrohen emoji" + "Nuk ke përdorur ende asnjë emoji" + "ndërruesi me dy drejtime për emoji-t" + "drejtimi i emoji-t u ndryshua" + "përzgjedhësi i variantit të emoji-t" + "%1$s dhe %2$s" + "hije" + "ton lëkure i zbehtë" + "ton lëkure mesatarisht i zbehtë" + "ton lëkure mesatar" + "ton lëkure mesatarisht i errët" + "ton lëkure i errët" + diff --git a/emojipicker/app/src/main/res/values-sr/strings.xml b/emojipicker/app/src/main/res/values-sr/strings.xml new file mode 100644 index 000000000..67d3619f0 --- /dev/null +++ b/emojipicker/app/src/main/res/values-sr/strings.xml @@ -0,0 +1,42 @@ + + + + + "НЕДАВНО КОРИШЋЕНО" + "СМАЈЛИЈИ И ЕМОЦИЈЕ" + "ЉУДИ" + "ЖИВОТИЊЕ И ПРИРОДА" + "ХРАНА И ПИЋЕ" + "ПУТОВАЊА И МЕСТА" + "АКТИВНОСТИ И ДОГАЂАЈИ" + "ОБЈЕКТИ" + "СИМБОЛИ" + "ЗАСТАВЕ" + "Емоџији нису доступни" + "Још нисте користили емоџије" + "двосмерни пребацивач емоџија" + "смер емоџија је промењен" + "бирач варијанти емоџија" + "%1$s и %2$s" + "сенка" + "кожа светле пути" + "кожа средњесветле пути" + "кожа средње пути" + "кожа средњетамне пути" + "кожа тамне пути" + diff --git a/emojipicker/app/src/main/res/values-sv/strings.xml b/emojipicker/app/src/main/res/values-sv/strings.xml new file mode 100644 index 000000000..dede0672c --- /dev/null +++ b/emojipicker/app/src/main/res/values-sv/strings.xml @@ -0,0 +1,42 @@ + + + + + "NYLIGEN ANVÄNDA" + "KÄNSLOIKONER OCH KÄNSLOR" + "PERSONER" + "DJUR OCH NATUR" + "MAT OCH DRYCK" + "RESOR OCH PLATSER" + "AKTIVITETER OCH HÄNDELSER" + "FÖREMÅL" + "SYMBOLER" + "FLAGGOR" + "Inga emojier tillgängliga" + "Du har ännu inte använt emojis" + "dubbelriktad emojiväxlare" + "emojins riktning har bytts" + "Väljare av emoji-varianter" + "%1$s och %2$s" + "skugga" + "ljus hudfärg" + "medelljus hudfärg" + "medelmörk hudfärg" + "mellanmörk hudfärg" + "mörk hudfärg" + diff --git a/emojipicker/app/src/main/res/values-sw/strings.xml b/emojipicker/app/src/main/res/values-sw/strings.xml new file mode 100644 index 000000000..3f7e24b06 --- /dev/null +++ b/emojipicker/app/src/main/res/values-sw/strings.xml @@ -0,0 +1,42 @@ + + + + + "ZILIZOTUMIKA HIVI MAJUZI" + "VICHESHI NA HISIA" + "WATU" + "WANYAMA NA MAZINGIRA" + "VYAKULA NA VINYWAJI" + "SAFARI NA MAENEO" + "SHUGHULI NA MATUKIO" + "VITU" + "ALAMA" + "BENDERA" + "Hakuna emoji zinazopatikana" + "Bado hujatumia emoji zozote" + "kibadilishaji cha emoji cha pande mbili" + "imebadilisha upande ambao emoji inaangalia" + "kiteuzi cha kibadala cha emoji" + "%1$s na %2$s" + "kivuli" + "ngozi ya rangi nyeupe" + "ngozi ya rangi nyeupe kiasi" + "ngozi ya rangi ya maji ya kunde" + "ngozi ya rangi nyeusi kiasi" + "ngozi ya rangi nyeusi" + diff --git a/emojipicker/app/src/main/res/values-ta/strings.xml b/emojipicker/app/src/main/res/values-ta/strings.xml new file mode 100644 index 000000000..5954c77f6 --- /dev/null +++ b/emojipicker/app/src/main/res/values-ta/strings.xml @@ -0,0 +1,42 @@ + + + + + "சமீபத்தில் பயன்படுத்தியவை" + "ஸ்மைலிகளும் எமோடிகான்களும்" + "நபர்" + "விலங்குகளும் இயற்கையும்" + "உணவும் பானமும்" + "பயணமும் இடங்களும்" + "செயல்பாடுகளும் நிகழ்வுகளும்" + "பொருட்கள்" + "சின்னங்கள்" + "கொடிகள்" + "ஈமோஜிகள் எதுவுமில்லை" + "இதுவரை ஈமோஜி எதையும் நீங்கள் பயன்படுத்தவில்லை" + "ஈமோஜி இருபக்க மாற்றி" + "ஈமோஜி காட்டப்படும் திசை மாற்றப்பட்டது" + "ஈமோஜி வகைத் தேர்வி" + "%1$s மற்றும் %2$s" + "நிழல்" + "வெள்ளை நிறம்" + "கொஞ்சம் வெள்ளை நிறம்" + "மாநிறம்" + "கொஞ்சம் கருநிறம்" + "கருநிறம்" + diff --git a/emojipicker/app/src/main/res/values-te/strings.xml b/emojipicker/app/src/main/res/values-te/strings.xml new file mode 100644 index 000000000..db21e73a6 --- /dev/null +++ b/emojipicker/app/src/main/res/values-te/strings.xml @@ -0,0 +1,42 @@ + + + + + "ఇటీవల ఉపయోగించినవి" + "స్మైలీలు, ఎమోషన్‌లు" + "వ్యక్తులు" + "జంతువులు, ప్రకృతి" + "ఆహారం, పానీయం" + "ప్రయాణం, స్థలాలు" + "యాక్టివిటీలు, ఈవెంట్‌లు" + "ఆబ్జెక్ట్‌లు" + "గుర్తులు" + "ఫ్లాగ్‌లు" + "ఎమోజీలు ఏవీ అందుబాటులో లేవు" + "మీరు ఇంకా ఎమోజీలు ఏవీ ఉపయోగించలేదు" + "ఎమోజీ ద్విదిశాత్మక స్విచ్చర్" + "ఎమోజీ దిశ మార్చబడింది" + "ఎమోజి రకాన్ని ఎంపిక చేసే సాధనం" + "%1$s, %2$s" + "షాడో" + "లైట్ స్కిన్ రంగు" + "చామనఛాయ లైట్ స్కిన్ రంగు" + "చామనఛాయ స్కిన్ రంగు" + "చామనఛాయ డార్క్ స్కిన్ రంగు" + "డార్క్ స్కిన్ రంగు" + diff --git a/emojipicker/app/src/main/res/values-th/strings.xml b/emojipicker/app/src/main/res/values-th/strings.xml new file mode 100644 index 000000000..74d28694e --- /dev/null +++ b/emojipicker/app/src/main/res/values-th/strings.xml @@ -0,0 +1,42 @@ + + + + + "ใช้ล่าสุด" + "หน้ายิ้มและอารมณ์" + "ผู้คน" + "สัตว์และธรรมชาติ" + "อาหารและเครื่องดื่ม" + "การเดินทางและสถานที่" + "กิจกรรมและเหตุการณ์" + "วัตถุ" + "สัญลักษณ์" + "ธง" + "ไม่มีอีโมจิ" + "คุณยังไม่ได้ใช้อีโมจิเลย" + "ตัวสลับอีโมจิแบบ 2 ทาง" + "เปลี่ยนทิศทางการหันหน้าของอีโมจิแล้ว" + "ตัวเลือกตัวแปรอีโมจิ" + "%1$s และ %2$s" + "เงา" + "โทนผิวสีอ่อน" + "โทนผิวสีอ่อนปานกลาง" + "โทนผิวสีปานกลาง" + "โทนผิวสีเข้มปานกลาง" + "โทนผิวสีเข้ม" + diff --git a/emojipicker/app/src/main/res/values-tl/strings.xml b/emojipicker/app/src/main/res/values-tl/strings.xml new file mode 100644 index 000000000..2a14fba77 --- /dev/null +++ b/emojipicker/app/src/main/res/values-tl/strings.xml @@ -0,0 +1,42 @@ + + + + + "KAMAKAILANG GINAMIT" + "MGA SMILEY AT MGA EMOSYON" + "MGA TAO" + "MGA HAYOP AT KALIKASAN" + "PAGKAIN AT INUMIN" + "PAGLALAKBAY AT MGA LUGAR" + "MGA AKTIBIDAD AT EVENT" + "MGA BAGAY" + "MGA SIMBOLO" + "MGA BANDILA" + "Walang available na emoji" + "Hindi ka pa gumamit ng anumang emoji" + "bidirectional na switcher ng emoji" + "pinalitan ang direksyon kung saan nakaharap ang emoji" + "selector ng variant ng emoji" + "%1$s at %2$s" + "shadow" + "maputing kulay ng balat" + "katamtamang maputing kulay ng balat" + "katamtamang kulay ng balat" + "katamtamang maitim na kulay ng balat" + "maitim na kulay ng balat" + diff --git a/emojipicker/app/src/main/res/values-tr/strings.xml b/emojipicker/app/src/main/res/values-tr/strings.xml new file mode 100644 index 000000000..f0d13cddf --- /dev/null +++ b/emojipicker/app/src/main/res/values-tr/strings.xml @@ -0,0 +1,42 @@ + + + + + "SON KULLANILANLAR" + "SMILEY\'LER VE İFADELER" + "İNSANLAR" + "HAYVANLAR VE DOĞA" + "YİYECEK VE İÇECEK" + "SEYAHAT VE YERLER" + "AKTİVİTELER VE ETKİNLİKLER" + "NESNELER" + "SEMBOLLER" + "BAYRAKLAR" + "Kullanılabilir emoji yok" + "Henüz emoji kullanmadınız" + "çift yönlü emoji değiştirici" + "emoji yönü değiştirildi" + "emoji varyant seçici" + "%1$s ve %2$s" + "gölge" + "açık ten rengi" + "orta-açık ten rengi" + "orta ten rengi" + "orta-koyu ten rengi" + "koyu ten rengi" + diff --git a/emojipicker/app/src/main/res/values-uk/strings.xml b/emojipicker/app/src/main/res/values-uk/strings.xml new file mode 100644 index 000000000..46e9e3dcd --- /dev/null +++ b/emojipicker/app/src/main/res/values-uk/strings.xml @@ -0,0 +1,42 @@ + + + + + "НЕЩОДАВНО ВИКОРИСТАНІ" + "СМАЙЛИКИ Й ЕМОЦІЇ" + "ЛЮДИ" + "ТВАРИНИ Й ПРИРОДА" + "ЇЖА Й НАПОЇ" + "ПОДОРОЖІ Й МІСЦЯ" + "АКТИВНІСТЬ І ПОДІЇ" + "ОБ’ЄКТИ" + "СИМВОЛИ" + "ПРАПОРИ" + "Немає смайлів" + "Ви ще не використовували смайли" + "двосторонній перемикач смайлів" + "змінено напрям обличчя смайлів" + "засіб вибору варіанта смайла" + "%1$s і %2$s" + "тінь" + "світлий відтінок шкіри" + "помірно світлий відтінок шкіри" + "помірний відтінок шкіри" + "помірно темний відтінок шкіри" + "темний відтінок шкіри" + diff --git a/emojipicker/app/src/main/res/values-ur/strings.xml b/emojipicker/app/src/main/res/values-ur/strings.xml new file mode 100644 index 000000000..68fa937dd --- /dev/null +++ b/emojipicker/app/src/main/res/values-ur/strings.xml @@ -0,0 +1,42 @@ + + + + + "حال ہی میں استعمال کردہ" + "اسمائلیز اور جذبات" + "لوگ" + "جانور اور قدرت" + "خوراک اور مشروب" + "سفر اور جگہیں" + "سرگرمیاں اور ایونٹس" + "آبجیکٹس" + "علامات" + "جھنڈے" + "کوئی بھی ایموجی دستیاب نہیں ہے" + "آپ نے ابھی تک کوئی بھی ایموجی استعمال نہیں کی ہے" + "دو طرفہ سوئچر ایموجی" + "ایموجی کا سمتِ رخ سوئچ کر دیا گیا" + "ایموجی کی قسم کا منتخب کنندہ" + "‏‎%1$s اور ‎%2$s" + "پرچھائیں" + "جلد کا ہلکا ٹون" + "جلد کا متوسط ہلکا ٹون" + "جلد کا متوسط ٹون" + "جلد کا متوسط گہرا ٹون" + "جلد کا گہرا ٹون" + diff --git a/emojipicker/app/src/main/res/values-uz/strings.xml b/emojipicker/app/src/main/res/values-uz/strings.xml new file mode 100644 index 000000000..6610ffd50 --- /dev/null +++ b/emojipicker/app/src/main/res/values-uz/strings.xml @@ -0,0 +1,42 @@ + + + + + "YAQINDA ISHLATILGAN" + "KULGICH VA EMOJILAR" + "ODAMLAR" + "HAYVONLAR VA TABIAT" + "TAOM VA ICHIMLIKLAR" + "SAYOHAT VA JOYLAR" + "HODISA VA TADBIRLAR" + "BUYUMLAR" + "BELGILAR" + "BAYROQCHALAR" + "Hech qanday emoji mavjud emas" + "Hanuz birorta emoji ishlatmagansiz" + "ikki tomonlama emoji almashtirgich" + "emoji yuzlanish tomoni almashdi" + "emoji variant tanlagich" + "%1$s va %2$s" + "soya" + "och rang tusli" + "oʻrtacha och rang tusli" + "neytral rang tusli" + "oʻrtacha toʻq rang tusli" + "toʻq rang tusli" + diff --git a/emojipicker/app/src/main/res/values-vi/strings.xml b/emojipicker/app/src/main/res/values-vi/strings.xml new file mode 100644 index 000000000..9e1eac8ec --- /dev/null +++ b/emojipicker/app/src/main/res/values-vi/strings.xml @@ -0,0 +1,42 @@ + + + + + "MỚI DÙNG GẦN ĐÂY" + "MẶT CƯỜI VÀ BIỂU TƯỢNG CẢM XÚC" + "MỌI NGƯỜI" + "ĐỘNG VẬT VÀ THIÊN NHIÊN" + "THỰC PHẨM VÀ ĐỒ UỐNG" + "DU LỊCH VÀ ĐỊA ĐIỂM" + "HOẠT ĐỘNG VÀ SỰ KIỆN" + "ĐỒ VẬT" + "BIỂU TƯỢNG" + "CỜ" + "Không có biểu tượng cảm xúc nào" + "Bạn chưa sử dụng biểu tượng cảm xúc nào" + "trình chuyển đổi hai chiều biểu tượng cảm xúc" + "đã chuyển hướng mặt của biểu tượng cảm xúc" + "bộ chọn biến thể biểu tượng cảm xúc" + "%1$s và %2$s" + "bóng" + "tông màu da sáng" + "tông màu da sáng trung bình" + "tông màu da trung bình" + "tông màu da tối trung bình" + "tông màu da tối" + diff --git a/emojipicker/app/src/main/res/values-zh-rCN/strings.xml b/emojipicker/app/src/main/res/values-zh-rCN/strings.xml new file mode 100644 index 000000000..453eb005a --- /dev/null +++ b/emojipicker/app/src/main/res/values-zh-rCN/strings.xml @@ -0,0 +1,42 @@ + + + + + "最近使用过" + "表情符号" + "人物" + "动物和自然" + "食品和饮料" + "旅游和地点" + "活动和庆典" + "物体" + "符号" + "旗帜" + "没有可用的表情符号" + "您尚未使用过任何表情符号" + "表情符号双向切换器" + "已切换表情符号朝向" + "表情符号变体选择器" + "%1$s和%2$s" + "阴影" + "浅肤色" + "中等偏浅肤色" + "中等肤色" + "中等偏深肤色" + "深肤色" + diff --git a/emojipicker/app/src/main/res/values-zh-rHK/strings.xml b/emojipicker/app/src/main/res/values-zh-rHK/strings.xml new file mode 100644 index 000000000..21b7318ff --- /dev/null +++ b/emojipicker/app/src/main/res/values-zh-rHK/strings.xml @@ -0,0 +1,42 @@ + + + + + "最近使用過" + "表情符號" + "人物" + "動物和大自然" + "飲食" + "旅遊和地點" + "活動和事件" + "物件" + "符號" + "旗幟" + "沒有可用的 Emoji" + "你尚未使用任何 Emoji" + "Emoji 雙向切換工具" + "轉咗 Emoji 方向" + "Emoji 變化版本選取器" + "%1$s和%2$s" + "陰影" + "淺膚色" + "偏淺膚色" + "中等膚色" + "偏深膚色" + "深膚色" + diff --git a/emojipicker/app/src/main/res/values-zh-rTW/strings.xml b/emojipicker/app/src/main/res/values-zh-rTW/strings.xml new file mode 100644 index 000000000..546e9de25 --- /dev/null +++ b/emojipicker/app/src/main/res/values-zh-rTW/strings.xml @@ -0,0 +1,42 @@ + + + + + "最近使用過" + "表情符號" + "人物" + "動物與大自然" + "飲食" + "旅行與地點" + "活動與事件" + "物品" + "符號" + "旗幟" + "沒有可用的表情符號" + "你尚未使用任何表情符號" + "表情符號雙向切換器" + "已切換表情符號方向" + "表情符號變化版本選取器" + "%1$s和%2$s" + "陰影" + "淺膚色" + "偏淺膚色" + "中等膚色" + "偏深膚色" + "深膚色" + diff --git a/emojipicker/app/src/main/res/values-zu/strings.xml b/emojipicker/app/src/main/res/values-zu/strings.xml new file mode 100644 index 000000000..3918f298b --- /dev/null +++ b/emojipicker/app/src/main/res/values-zu/strings.xml @@ -0,0 +1,42 @@ + + + + + "EZISANDA KUSETSHENZISWA" + "AMASMAYILI NEMIZWA" + "ABANTU" + "IZILWANE NENDALO" + "UKUDLA NESIPHUZO" + "UKUVAKASHA NEZINDAWO" + "IMISEBENZI NEMICIMBI" + "IZINTO" + "AMASIMBULI" + "AMAFULEGI" + "Awekho ama-emoji atholakalayo" + "Awukasebenzisi noma yimaphi ama-emoji okwamanje" + "isishintshi se-emoji ye-bidirectional" + "isikhombisi-ndlela esibheke ku-emoji sishintshiwe" + "isikhethi esihlukile se-emoji" + "Okuthi %1$s nokuthi %2$s" + "isithunzi" + "ibala lesikhumba elikhanyayo" + "ibala lesikhumba elikhanya ngokumaphakathi" + "ibala lesikhumba eliphakathi nendawo" + "ibala lesikhumba elinsundu ngokumaphakathi" + "ibala lesikhumba elimnyama" + diff --git a/emojipicker/app/src/main/res/values/arrays.xml b/emojipicker/app/src/main/res/values/arrays.xml new file mode 100644 index 000000000..8c1328962 --- /dev/null +++ b/emojipicker/app/src/main/res/values/arrays.xml @@ -0,0 +1,54 @@ + + + + + + @raw/emoji_category_emotions + @raw/emoji_category_people + @raw/emoji_category_animals_nature + @raw/emoji_category_food_drink + @raw/emoji_category_travel_places + @raw/emoji_category_activity + @raw/emoji_category_objects + @raw/emoji_category_symbols + @raw/emoji_category_flags + + + + + @raw/emoji_category_emotions + + @raw/emoji_category_animals_nature + @raw/emoji_category_food_drink + @raw/emoji_category_travel_places + @raw/emoji_category_activity + @raw/emoji_category_objects + @raw/emoji_category_symbols + @raw/emoji_category_flags + + + + @drawable/gm_filled_emoji_emotions_vd_theme_24 + @drawable/gm_filled_emoji_people_vd_theme_24 + @drawable/gm_filled_emoji_nature_vd_theme_24 + @drawable/gm_filled_emoji_food_beverage_vd_theme_24 + @drawable/gm_filled_emoji_transportation_vd_theme_24 + @drawable/gm_filled_emoji_events_vd_theme_24 + @drawable/gm_filled_emoji_objects_vd_theme_24 + @drawable/gm_filled_emoji_symbols_vd_theme_24 + @drawable/gm_filled_flag_vd_theme_24 + + + + @string/emoji_category_emotions + @string/emoji_category_people + @string/emoji_category_animals_nature + @string/emoji_category_food_drink + @string/emoji_category_travel_places + @string/emoji_category_activity + @string/emoji_category_objects + @string/emoji_category_symbols + @string/emoji_category_flags + + \ No newline at end of file diff --git a/emojipicker/app/src/main/res/values/attrs.xml b/emojipicker/app/src/main/res/values/attrs.xml new file mode 100644 index 000000000..c84e3d86a --- /dev/null +++ b/emojipicker/app/src/main/res/values/attrs.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/main/res/values/colors.xml b/emojipicker/app/src/main/res/values/colors.xml new file mode 100644 index 000000000..62ab68f23 --- /dev/null +++ b/emojipicker/app/src/main/res/values/colors.xml @@ -0,0 +1,12 @@ + + + + + #edbd82 + #ba8f63 + #91674d + #875334 + #4a2f27 + + #ffffff + diff --git a/emojipicker/app/src/main/res/values/dimens.xml b/emojipicker/app/src/main/res/values/dimens.xml new file mode 100644 index 000000000..fb44ef4da --- /dev/null +++ b/emojipicker/app/src/main/res/values/dimens.xml @@ -0,0 +1,24 @@ + + + + + 39dp + 46dp + 20dp + 20dp + 28dp + 2dp + 42dp + 5dp + 5dp + 5dp + 10dp + 10dp + 10dp + 8dp + 30dp + 6dp + 24dp + 4dp + 2dp + \ No newline at end of file diff --git a/emojipicker/app/src/main/res/values/strings.xml b/emojipicker/app/src/main/res/values/strings.xml new file mode 100644 index 000000000..ddfd2110c --- /dev/null +++ b/emojipicker/app/src/main/res/values/strings.xml @@ -0,0 +1,61 @@ + + + + + RECENTLY USED + + SMILEYS AND EMOTIONS + + PEOPLE + + ANIMALS AND NATURE + + FOOD AND DRINK + + TRAVEL AND PLACES + + ACTIVITIES AND EVENTS + + OBJECTS + + SYMBOLS + + FLAGS + + + No emojis available + + You haven\'t used any emojis yet + + + emoji bidirectional switcher + + + emoji facing direction switched + + + emoji variant selector + + + %1$s and %2$s + + + shadow + + + light skin tone + + + medium light skin tone + + + medium skin tone + + + medium dark skin tone + + + dark skin tone + diff --git a/emojipicker/app/src/main/res/values/styles.xml b/emojipicker/app/src/main/res/values/styles.xml new file mode 100644 index 000000000..7f7fd86a4 --- /dev/null +++ b/emojipicker/app/src/main/res/values/styles.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + diff --git a/emojipicker/app/src/test/java/com/rishabh/emojipicker/ExampleUnitTest.kt b/emojipicker/app/src/test/java/com/rishabh/emojipicker/ExampleUnitTest.kt new file mode 100644 index 000000000..a2585b6ee --- /dev/null +++ b/emojipicker/app/src/test/java/com/rishabh/emojipicker/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package com.rishabh.emojipicker + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} \ No newline at end of file diff --git a/emojipicker/build.gradle.kts b/emojipicker/build.gradle.kts new file mode 100644 index 000000000..64b53a935 --- /dev/null +++ b/emojipicker/build.gradle.kts @@ -0,0 +1,59 @@ +plugins { + id("com.android.library") + id("org.jetbrains.kotlin.android") +} + +android { + namespace = "com.rishabh.emojipicker" + compileSdk = 34 + + defaultConfig { + minSdk = project.libs.versions.app.build.minimumSDK.get().toInt() + targetSdk = 34 + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = "1.8" + } +} + +dependencies { + + implementation("androidx.core:core-ktx:1.13.1") + implementation("androidx.appcompat:appcompat:1.7.0") + implementation("com.google.android.material:material:1.12.0") + implementation("androidx.emoji2:emoji2:1.4.0") + implementation("com.google.firebase:firebase-crashlytics-buildtools:3.0.0") + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.5") + androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") + implementation ("org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.7.3") + api("androidx.core:core:1.9.0") + + // Implementations + implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.22") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.7.3") + + + androidTestImplementation("androidx.test:core:1.5.0") + androidTestImplementation("androidx.test:runner:1.5.2") + androidTestImplementation("androidx.test:rules:1.5.0") + + + +} diff --git a/emojipicker/consumer-rules.pro b/emojipicker/consumer-rules.pro new file mode 100644 index 000000000..e69de29bb diff --git a/emojipicker/gradle.properties b/emojipicker/gradle.properties new file mode 100644 index 000000000..3c5031eb7 --- /dev/null +++ b/emojipicker/gradle.properties @@ -0,0 +1,23 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official +# Enables namespacing of each library's R class so that its R class includes only the +# resources declared in the library itself and none from the library's dependencies, +# thereby reducing the size of the R class for that library +android.nonTransitiveRClass=true \ No newline at end of file diff --git a/emojipicker/gradle/libs.versions.toml b/emojipicker/gradle/libs.versions.toml new file mode 100644 index 000000000..d4617a1cf --- /dev/null +++ b/emojipicker/gradle/libs.versions.toml @@ -0,0 +1,26 @@ +[versions] +kotlinStdlib = "1.10.0-alpha01" +kotlinCoroutinesAndroid = "1.9.0-alpha01" +kotlinCoroutinesGuava = "1.4.0-rc01" +espressoContrib = "1.7.0-rc01" +espressoCore = "1.1.0-alpha04" +testCore = "2.3.0-alpha01" +testExtJunit = "1.1.0-alpha02" +testRunner = "1.3.0-alpha02" +testRules = "1.3.0-alpha05" + +[libraries] +#AndroidX +#kotlinStdlib = { module = "androidx.kotlinStdlib", version.ref = "1.10.0-alpha01" } +#kotlinCoroutinesAndroid = { module = "androidx.kotlinCoroutinesAndroid", version.ref = "1.9.0-alpha01" } +#kotlinCoroutinesGuava = { module = "androidx.kotlinCoroutinesGuava", version.ref = "1.4.0-rc01" } +#espressoCore = { module = "androidx.espressoCore", version.ref = "1.1.0-alpha04" } +#testCore = { module = "androidx.testCore", version.ref = "2.3.0-alpha01" } +#testExtJunit = { module = "androidx.testExtJunit", version.ref = "1.1.0-alpha02" } +#testRunner = { module = "androidx.testRunner", version.ref = "1.3.0-alpha02" } +#testRules = { module = "androidx.testRules", version.ref = "1.3.0-alpha05" } + +[bundles] +#espressoContrib = { module = "androidx.bundles.espressoContrib", version.ref = "1.7.0-rc01" } + + diff --git a/emojipicker/gradle/wrapper/gradle-wrapper.jar b/emojipicker/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..e708b1c02 Binary files /dev/null and b/emojipicker/gradle/wrapper/gradle-wrapper.jar differ diff --git a/emojipicker/gradle/wrapper/gradle-wrapper.properties b/emojipicker/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..c6a783c59 --- /dev/null +++ b/emojipicker/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sat Jun 01 17:24:43 IST 2024 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/emojipicker/gradlew b/emojipicker/gradlew new file mode 100644 index 000000000..4f906e0c8 --- /dev/null +++ b/emojipicker/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/emojipicker/gradlew.bat b/emojipicker/gradlew.bat new file mode 100644 index 000000000..107acd32c --- /dev/null +++ b/emojipicker/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/emojipicker/proguard-rules.pro b/emojipicker/proguard-rules.pro new file mode 100644 index 000000000..481bb4348 --- /dev/null +++ b/emojipicker/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/emojipicker/src/androidTest/java/com/rishabh/emojipicker/ExampleInstrumentedTest.kt b/emojipicker/src/androidTest/java/com/rishabh/emojipicker/ExampleInstrumentedTest.kt new file mode 100644 index 000000000..4f45e2e15 --- /dev/null +++ b/emojipicker/src/androidTest/java/com/rishabh/emojipicker/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.rishabh.emojipicker + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.rishabh.emojipicker.test", appContext.packageName) + } +} \ No newline at end of file diff --git a/emojipicker/src/main/AndroidManifest.xml b/emojipicker/src/main/AndroidManifest.xml new file mode 100644 index 000000000..92dab7766 --- /dev/null +++ b/emojipicker/src/main/AndroidManifest.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/emojipicker/src/main/androidx/emoji2/androidx-emoji2-emoji2-emojipicker-documentation.md b/emojipicker/src/main/androidx/emoji2/androidx-emoji2-emoji2-emojipicker-documentation.md new file mode 100644 index 000000000..fc1b9355e --- /dev/null +++ b/emojipicker/src/main/androidx/emoji2/androidx-emoji2-emoji2-emojipicker-documentation.md @@ -0,0 +1,8 @@ +# Module root + +androidx.emoji2 emoji2-emojipicker + +# package reeshabh.emojipicker + +This library provides the latest emoji support and emoji picker UI including +skin-tone variants and emoji compat support. diff --git a/emojipicker/src/main/java/androidx/emoji2/emojipicker/BundledEmojiListLoader.kt b/emojipicker/src/main/java/androidx/emoji2/emojipicker/BundledEmojiListLoader.kt new file mode 100644 index 000000000..6b8df3ca4 --- /dev/null +++ b/emojipicker/src/main/java/androidx/emoji2/emojipicker/BundledEmojiListLoader.kt @@ -0,0 +1,145 @@ + + +package com.rishabh.emojipicker + +import android.content.Context +import android.content.res.TypedArray +import android.util.Log +import androidx.annotation.DrawableRes +import androidx.core.content.res.use +import com.rishabh.emojipicker.utils.UnicodeRenderableManager +import com.rishabh.emojipicker.utils.FileCache + +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.coroutineScope + +/** + * A data loader that loads the following objects either from file based caches or from resources. + * + * categorizedEmojiData: a list that holds bundled emoji separated by category, filtered by + * renderability check. This is the data source for EmojiPickerView. + * + * emojiVariantsLookup: a map of emoji variants in bundled emoji, keyed by the base emoji. This + * allows faster variants lookup. + * + * primaryEmojiLookup: a map of base emoji to its variants in bundled emoji. This allows faster + * variants lookup. + */ + object BundledEmojiListLoader { + private var categorizedEmojiData: List? = null + private var emojiVariantsLookup: Map>? = null + + internal suspend fun load(context: Context) { + val categoryNames = context.resources.getStringArray(R.array.category_names) + val categoryHeaderIconIds = + context.resources.obtainTypedArray(R.array.emoji_categories_icons).use { typedArray -> + IntArray(typedArray.length()) { + typedArray.getResourceId(it, 0) + } + } + + /*may be have issue in the old android version- the part i comment it out*/ + val resources = +// if (UnicodeRenderableManager.isEmoji12Supported()) +// R.array.emoji_by_category_raw_resources_gender_inclusive +// else + R.array.emoji_by_category_raw_resources + val emojiFileCache = FileCache.getInstance(context) + + categorizedEmojiData = + context.resources.obtainTypedArray(resources).use { ta -> + loadEmoji(ta, categoryHeaderIconIds, categoryNames, emojiFileCache, context) + } + emojiVariantsLookup = + categorizedEmojiData!! + .flatMap { it.emojiDataList } + .filter { it.variants.isNotEmpty() } + .flatMap { it.variants.map { variant -> EmojiViewItem(it.emoji, it.description, it.variants) } } + .associate { it.emoji to it.variants } + .also { + emojiVariantsLookup = it } + } + + fun getCategorizedEmojiData() = + categorizedEmojiData + ?: throw IllegalStateException("BundledEmojiListLoader.load is not called or complete") + + fun getEmojiVariantsLookup() = + emojiVariantsLookup + ?: throw IllegalStateException("BundledEmojiListLoader.load is not called or complete") + + private suspend fun loadEmoji( + ta: TypedArray, + @DrawableRes categoryHeaderIconIds: IntArray, + categoryNames: Array, + emojiFileCache: FileCache, + context: Context + ): List = coroutineScope { + (0 until ta.length()) + .map {intvalue-> + async { + emojiFileCache + .getOrPut(getCacheFileName(intvalue)) { + loadSingleCategory(context, ta.getResourceId(intvalue, 0)) + }.let { + + EmojiDataCategory(categoryHeaderIconIds[intvalue], categoryNames[intvalue], it) + } + } + } + .awaitAll() + } + + private fun loadSingleCategory( + context: Context, + csvResId: Int, + ): List = + context.resources + .openRawResource(csvResId) + .bufferedReader() + .useLines { it.toList() } + .map { + filterRenderableEmojis(it.split(",")) + } + .filter { + it.isNotEmpty() } + .map { + val emoji = it.getOrNull(0) ?: "" + val description = it.getOrNull(1) ?:"" + + Log.i("hehe23he", description.toString()) + EmojiViewItem(emoji, description,it.drop(2)) } + + private fun getCacheFileName(categoryIndex: Int) = + StringBuilder() + .append("emoji.v1.") + .append(if (EmojiPickerView.emojiCompatLoaded) 1 else 0) + .append(".") + .append(categoryIndex) + .append(".") + .append(if (UnicodeRenderableManager.isEmoji12Supported()) 1 else 0) + .toString() + + /** + * To eliminate 'Tofu' (the fallback glyph when an emoji is not renderable), check the + * renderability of emojis and keep only when they are renderable on the current device. + */ + private fun filterRenderableEmojis(emojiList: List) :List{ + if(UnicodeRenderableManager.isEmojiRenderable(emojiList.first())){ + for(varient in emojiList.drop(2)){ + if(UnicodeRenderableManager.isEmojiRenderable((varient).toString())){ + return emojiList + } + } + return emojiList + + } + return listOf() + } + data class EmojiDataCategory( + @DrawableRes val headerIconId: Int, + val categoryName: String, + val emojiDataList: List + ) +} diff --git a/emojipicker/src/main/java/androidx/emoji2/emojipicker/DefaultRecentEmojiProvider.kt b/emojipicker/src/main/java/androidx/emoji2/emojipicker/DefaultRecentEmojiProvider.kt new file mode 100644 index 000000000..f525b5dd6 --- /dev/null +++ b/emojipicker/src/main/java/androidx/emoji2/emojipicker/DefaultRecentEmojiProvider.kt @@ -0,0 +1,40 @@ +package com.rishabh.emojipicker + +import android.content.Context +import android.content.Context.MODE_PRIVATE + +/** + * Provides recently shared emoji. This is the default recent emoji list provider. Clients could + * specify the provider by their own. + */ +internal class DefaultRecentEmojiProvider(context: Context) : RecentEmojiProvider { + + companion object { + private const val PREF_KEY_RECENT_EMOJI = "pref_key_recent_emoji" + private const val RECENT_EMOJI_LIST_FILE_NAME = "androidx.emoji2.emojipicker.preferences" + private const val SPLIT_CHAR = "," + } + + private val sharedPreferences = + context.getSharedPreferences(RECENT_EMOJI_LIST_FILE_NAME, MODE_PRIVATE) + private val recentEmojiList: MutableList = + sharedPreferences.getString(PREF_KEY_RECENT_EMOJI, null)?.split(SPLIT_CHAR)?.toMutableList() + ?: mutableListOf() + + override suspend fun getRecentEmojiList(): List { + return recentEmojiList + } + + override fun recordSelection(emoji: String) { + recentEmojiList.remove(emoji) + recentEmojiList.add(0, emoji) + saveToPreferences() + } + + private fun saveToPreferences() { + sharedPreferences + .edit() + .putString(PREF_KEY_RECENT_EMOJI, recentEmojiList.joinToString(SPLIT_CHAR)) + .commit() + } +} diff --git a/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerBodyAdapter.kt b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerBodyAdapter.kt new file mode 100644 index 000000000..2a776b444 --- /dev/null +++ b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerBodyAdapter.kt @@ -0,0 +1,156 @@ + + +package com.rishabh.emojipicker + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.ViewGroup.LayoutParams +import android.widget.TextView +import androidx.annotation.LayoutRes +import androidx.annotation.UiThread +import androidx.core.view.ViewCompat + +import androidx.recyclerview.widget.RecyclerView.Adapter +import androidx.recyclerview.widget.RecyclerView.ViewHolder +import com.rishabh.emojipicker.Extensions.toItemType + +/** RecyclerView adapter for emoji body. */ +class EmojiPickerBodyAdapter( + private val context: Context, + private val emojiGridColumns: Int, + private val emojiGridRows: Float?, + private val stickyVariantProvider: StickyVariantProvider, + private val emojiPickerItemsProvider: () -> EmojiPickerItems, + private val onEmojiPickedListener: EmojiPickerBodyAdapter.(EmojiViewItem) -> Unit, + var hideTitleAndEmptyHint:Boolean = false +) : Adapter() { + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + private var emojiCellWidth: Int? = null + private var emojiCellHeight: Int? = null + + + + @UiThread + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + emojiCellWidth = emojiCellWidth ?: (getParentWidth(parent) / emojiGridColumns) + emojiCellHeight = + emojiCellHeight + ?: emojiGridRows?.let { getEmojiCellTotalHeight(parent) / it }?.toInt() + ?: emojiCellWidth + if(hideTitleAndEmptyHint){ + + } + + return when (viewType.toItemType()) { + ItemType.CATEGORY_TITLE -> createSimpleHolder(R.layout.category_text_view, parent) + + ItemType.PLACEHOLDER_TEXT -> + createSimpleHolder(R.layout.empty_category_text_view, parent) { + minimumHeight = emojiCellHeight!! + } + + ItemType.EMOJI -> { + EmojiViewHolder( + context, + emojiCellWidth!!, + emojiCellHeight!!, + stickyVariantProvider, + onEmojiPickedListener = { emojiViewItem -> + onEmojiPickedListener(emojiViewItem) + }, + onEmojiPickedFromPopupListener = { emoji -> + var baseEmoji = "" + BundledEmojiListLoader.getEmojiVariantsLookup().forEach { key,value-> + value.forEach { + if(it==emoji){ + baseEmoji = key + } + } + } + emojiPickerItemsProvider().forEachIndexed { index, itemViewData -> + if ( + itemViewData is EmojiViewData && + BundledEmojiListLoader.getEmojiVariantsLookup()[ + itemViewData.emoji] + ?.get(0) == baseEmoji && + itemViewData.updateToSticky + ) { + itemViewData.emoji = emoji + notifyItemChanged(index) + } + } + } + ) + } + } + } + + override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) { + val item = emojiPickerItemsProvider().getBodyItem(position) + + if(hideTitleAndEmptyHint){ + when (getItemViewType(position).toItemType()) { + ItemType.CATEGORY_TITLE -> {} + ItemType.PLACEHOLDER_TEXT -> {} + + ItemType.EMOJI -> { + (viewHolder as EmojiViewHolder).bindEmoji((item as EmojiViewData).emoji) + } + } + }else{ + when (getItemViewType(position).toItemType()) { + ItemType.CATEGORY_TITLE -> { + ViewCompat.requireViewById(viewHolder.itemView, R.id.category_name).text = + (item as CategoryTitle).title + } + ItemType.EMOJI -> { + (viewHolder as EmojiViewHolder).bindEmoji((item as EmojiViewData).emoji) + } + ItemType.PLACEHOLDER_TEXT -> { + ViewCompat.requireViewById( + viewHolder.itemView, + R.id.emoji_picker_empty_category_view + ) + .text = (item as PlaceholderText).text + } + } + } + + } + + override fun getItemId(position: Int): Long = + emojiPickerItemsProvider().getBodyItem(position).hashCode().toLong() + + override fun getItemCount(): Int { + return emojiPickerItemsProvider().size + } + + override fun getItemViewType(position: Int): Int { + return emojiPickerItemsProvider().getBodyItem(position).viewType + } + + private fun getParentWidth(parent: ViewGroup): Int { + return parent.measuredWidth - parent.paddingLeft - parent.paddingRight + } + + private fun getEmojiCellTotalHeight(parent: ViewGroup) = + parent.measuredHeight - + context.resources.getDimensionPixelSize(R.dimen.emoji_picker_category_name_height) * 2 - + context.resources.getDimensionPixelSize(R.dimen.emoji_picker_category_name_padding_top) + + private fun createSimpleHolder( + @LayoutRes layoutId: Int, + parent: ViewGroup, + init: (View.() -> Unit)? = null, + ) = + object : + ViewHolder( + layoutInflater.inflate(layoutId, parent, /* attachToRoot= */ false).also { + it.layoutParams = + LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT) + init?.invoke(it) + } + ) {} +} diff --git a/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerConstants.kt b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerConstants.kt new file mode 100644 index 000000000..e7e8d2a40 --- /dev/null +++ b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerConstants.kt @@ -0,0 +1,21 @@ + + +package com.rishabh.emojipicker + +/** A utility class to hold various constants used by the Emoji Picker library. */ +internal object EmojiPickerConstants { + + // The default number of body columns. + const val DEFAULT_BODY_COLUMNS = 9 + + // The default number of rows of recent items held. + const val DEFAULT_MAX_RECENT_ITEM_ROWS = 3 + + // The max pool size of the Emoji ItemType in RecyclerViewPool. + const val EMOJI_VIEW_POOL_SIZE = 100 + + const val ADD_VIEW_EXCEPTION_MESSAGE = "Adding views to the EmojiPickerView is unsupported" + + const val REMOVE_VIEW_EXCEPTION_MESSAGE = + "Removing views from the EmojiPickerView is unsupported" +} diff --git a/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerHeaderAdapter.kt b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerHeaderAdapter.kt new file mode 100644 index 000000000..a6c3dd010 --- /dev/null +++ b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerHeaderAdapter.kt @@ -0,0 +1,74 @@ + + +package com.rishabh.emojipicker + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.accessibility.AccessibilityEvent +import android.widget.ImageView +import androidx.core.view.ViewCompat +import androidx.recyclerview.widget.RecyclerView.Adapter +import androidx.recyclerview.widget.RecyclerView.ViewHolder + +/** RecyclerView adapter for emoji header. */ +internal class EmojiPickerHeaderAdapter( + context: Context, + private val emojiPickerItems: EmojiPickerItems, + private val onHeaderIconClicked: (Int) -> Unit, +) : Adapter() { + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + + var selectedGroupIndex: Int = 0 + set(value) { + if (value == field) return + notifyItemChanged(field) + notifyItemChanged(value) + field = value + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + return object : + ViewHolder( + layoutInflater.inflate( + R.layout.header_icon_holder, + parent, + /* attachToRoot = */ false + ) + ) {} + } + + override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) { + val isItemSelected = i == selectedGroupIndex + val headerIcon = + ViewCompat.requireViewById( + viewHolder.itemView, + R.id.emoji_picker_header_icon + ) + .apply { + setImageDrawable(context.getDrawable(emojiPickerItems.getHeaderIconId(i))) + isSelected = isItemSelected + contentDescription = emojiPickerItems.getHeaderIconDescription(i) + } + viewHolder.itemView.setOnClickListener { + onHeaderIconClicked(i) + selectedGroupIndex = i + } + if (isItemSelected) { + headerIcon.post { + headerIcon.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER) + } + } + + ViewCompat.requireViewById(viewHolder.itemView, R.id.emoji_picker_header_underline) + .apply { + visibility = if (isItemSelected) View.VISIBLE else View.GONE + isSelected = isItemSelected + } + } + + override fun getItemCount(): Int { + return emojiPickerItems.numGroups + } +} diff --git a/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerItems.kt b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerItems.kt new file mode 100644 index 000000000..a63396a80 --- /dev/null +++ b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerItems.kt @@ -0,0 +1,103 @@ + + +package com.rishabh.emojipicker + +import androidx.annotation.DrawableRes +import androidx.annotation.IntRange + +/** + * A group of items in RecyclerView for emoji picker body. [titleItem] comes first. [listOfAllEmojiInAGroup] + * comes after [titleItem]. [emptyPlaceholderItem] will be served after [titleItem] only if + * [listOfAllEmojiInAGroup] is empty. [maxContentItemCount], if provided, will truncate [listOfAllEmojiInAGroup] to + * certain size. + * + * [categoryIconId] is the corresponding category icon in emoji picker header. + */ +class ItemGroup( + @DrawableRes internal val categoryIconId: Int, + internal val titleItem: CategoryTitle, + private val listOfAllEmojiInAGroup: List, + private val maxContentItemCount: Int? = null, + private val emptyPlaceholderItem: PlaceholderText? = null +) { + + val size: Int + get() { + var totalSize = 1 // Start with the title item + + // Check for empty content items and adjust size accordingly + if (listOfAllEmojiInAGroup.isEmpty()) { + totalSize += if (emptyPlaceholderItem!= null) 1 else 0 + } else { + // Adjust size based on maxContentItemCount if applicable + if (maxContentItemCount!= null && listOfAllEmojiInAGroup.size > maxContentItemCount) { + totalSize = maxContentItemCount + } else { + totalSize += listOfAllEmojiInAGroup.size // Add the actual number of content items + } + } + + return totalSize + } + + operator fun get(index: Int): ItemViewData { + if (index == 0) return titleItem + val contentIndex = index - 1 + if (contentIndex < listOfAllEmojiInAGroup.size) return listOfAllEmojiInAGroup[contentIndex] + if (contentIndex == 0 && emptyPlaceholderItem != null) return emptyPlaceholderItem + throw IndexOutOfBoundsException() + } + + fun getAll(): List = IntRange(0, size - 1).map { get(it) } +} + +/** A view of concatenated list of [ItemGroup]. */ +class EmojiPickerItems(private val groups: List ) : Iterable { + val size: Int + get() = groups.sumOf { it.size } + + + + fun getBodyItem(@IntRange(from = 0) absolutePosition: Int): ItemViewData { + var localPosition = absolutePosition + for (group in groups) { + + if (localPosition < group.size) return group[localPosition] + else localPosition -= group.size + } + throw IndexOutOfBoundsException() + } + + val numGroups: Int + get() = groups.size + + @DrawableRes + fun getHeaderIconId(@IntRange(from = 0) index: Int): Int = groups[index].categoryIconId + + fun getHeaderIconDescription(@IntRange(from = 0) index: Int): String = + groups[index].titleItem.title + + fun groupIndexByItemPosition(@IntRange(from = 0) absolutePosition: Int): Int { + var localPosition = absolutePosition + var index = 0 + for (group in groups) { + if (localPosition < group.size) return index + else { + localPosition -= group.size + index++ + } + } + throw IndexOutOfBoundsException() + } + + fun firstItemPositionByGroupIndex(@IntRange(from = 0) groupIndex: Int): Int = + groups.take(groupIndex).sumOf { it.size } + + fun groupRange(group: ItemGroup): kotlin.ranges.IntRange { + check(groups.contains(group)) + val index = groups.indexOf(group) + return firstItemPositionByGroupIndex(index).let { it until it + group.size } + } + + override fun iterator(): Iterator = groups.flatMap { it.getAll() }.iterator() +} diff --git a/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupBidirectionalDesign.kt b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupBidirectionalDesign.kt new file mode 100644 index 000000000..1829233f3 --- /dev/null +++ b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupBidirectionalDesign.kt @@ -0,0 +1,110 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.rishabh.emojipicker + +import android.content.Context +import android.view.Gravity +import android.view.View +import android.view.ViewGroup +import android.widget.FrameLayout +import android.widget.LinearLayout +import androidx.appcompat.widget.AppCompatImageView + +/** Emoji picker popup view with bidirectional UI design to switch emoji to face left or right. */ +internal class EmojiPickerPopupBidirectionalDesign( + override val context: Context, + override val targetEmojiView: View, + override val variants: List, + override val popupView: LinearLayout, + override val emojiViewOnClickListener: View.OnClickListener +) : EmojiPickerPopupDesign() { + private var emojiFacingLeft = true + + init { + updateTemplate() + } + + override fun addLayoutHeader() { + val row = + LinearLayout(context).apply { + orientation = LinearLayout.HORIZONTAL + gravity = Gravity.CENTER + layoutParams = + LinearLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + } + FrameLayout.inflate(context, R.layout.emoji_picker_popup_bidirectional, row) + .findViewById(R.id.emoji_picker_popup_bidirectional_icon) + .apply { + layoutParams = + LinearLayout.LayoutParams(targetEmojiView.width, targetEmojiView.height) + } + popupView.addView(row) + val imageView = + row.findViewById(R.id.emoji_picker_popup_bidirectional_icon) + imageView.setOnClickListener { + emojiFacingLeft = !emojiFacingLeft + updateTemplate() + popupView.removeViews(/* start= */ 1, getActualNumberOfRows()) + addRowsToPopupView() + imageView.announceForAccessibility( + context.getString(R.string.emoji_bidirectional_switcher_clicked_desc) + ) + } + } + + override fun getNumberOfRows(): Int { + // Adding one row for the bidirectional switcher. + return variants.size / 2 / BIDIRECTIONAL_COLUMN_COUNT + 1 + } + + override fun getNumberOfColumns(): Int { + return BIDIRECTIONAL_COLUMN_COUNT + } + + private fun getActualNumberOfRows(): Int { + // Removing one extra row of the bidirectional switcher. + return getNumberOfRows() - 1 + } + + private fun updateTemplate() { + template = + if (emojiFacingLeft) + arrayOf((variants.indices.filter { it % 12 < 6 }.map { it + 1 }).toIntArray()) + else arrayOf((variants.indices.filter { it % 12 >= 6 }.map { it + 1 }).toIntArray()) + + val row = getActualNumberOfRows() + val column = getNumberOfColumns() + val overrideTemplate = Array(row) { IntArray(column) } + var index = 0 + for (i in 0 until row) { + for (j in 0 until column) { + if (index < template[0].size) { + overrideTemplate[i][j] = template[0][index] + index++ + } + } + } + template = overrideTemplate + } + + companion object { + private const val BIDIRECTIONAL_COLUMN_COUNT = 6 + } +} diff --git a/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupDesign.kt b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupDesign.kt new file mode 100644 index 000000000..e55f53df5 --- /dev/null +++ b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupDesign.kt @@ -0,0 +1,89 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.rishabh.emojipicker + +import android.content.Context +import android.view.View +import android.view.ViewGroup +import android.view.accessibility.AccessibilityEvent +import android.widget.FrameLayout +import android.widget.LinearLayout + +/** Emoji picker popup view UI design. Each UI design needs to inherit this abstract class. */ +internal abstract class EmojiPickerPopupDesign { + abstract val context: Context + abstract val targetEmojiView: View + abstract val variants: List + abstract val popupView: LinearLayout + abstract val emojiViewOnClickListener: View.OnClickListener + lateinit var template: Array + + open fun addLayoutHeader() { + // no-ops + } + + open fun addRowsToPopupView() { + for (row in template) { + val rowLayout = + LinearLayout(context).apply { + orientation = LinearLayout.HORIZONTAL + layoutParams = + LinearLayout.LayoutParams( + FrameLayout.LayoutParams.WRAP_CONTENT, + FrameLayout.LayoutParams.WRAP_CONTENT + ) + } + for (item in row) { + val cell = + if (item == 0) { + EmojiView(context) + } else { + EmojiView(context).apply { + willDrawVariantIndicator = false + emoji = variants[item - 1] + setOnClickListener(emojiViewOnClickListener) + if (item == 1) { + // Hover on the first emoji in the popup + popupView.post { + sendAccessibilityEvent( + AccessibilityEvent.TYPE_VIEW_HOVER_ENTER + ) + } + } + } + } + .apply { + layoutParams = + ViewGroup.LayoutParams( + targetEmojiView.width, + targetEmojiView.height + ) + } + rowLayout.addView(cell) + } + popupView.addView(rowLayout) + } + } + + open fun addLayoutFooter() { + // no-ops + } + + abstract fun getNumberOfRows(): Int + + abstract fun getNumberOfColumns(): Int +} diff --git a/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupFlatDesign.kt b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupFlatDesign.kt new file mode 100644 index 000000000..4b5112568 --- /dev/null +++ b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupFlatDesign.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.rishabh.emojipicker + +import android.content.Context +import android.view.View +import android.widget.LinearLayout + +/** Emoji picker popup view with flat design to list emojis. */ +internal class EmojiPickerPopupFlatDesign( + override val context: Context, + override val targetEmojiView: View, + override val variants: List, + override val popupView: LinearLayout, + override val emojiViewOnClickListener: View.OnClickListener +) : EmojiPickerPopupDesign() { + init { + template = arrayOf(variants.indices.map { it + 1 }.toIntArray()) + var row = getNumberOfRows() + var column = getNumberOfColumns() + val overrideTemplate = Array(row) { IntArray(column) } + var index = 0 + for (i in 0 until row) { + for (j in 0 until column) { + if (index < template[0].size) { + overrideTemplate[i][j] = template[0][index] + index++ + } + } + } + template = overrideTemplate + } + + override fun getNumberOfRows(): Int { + val column = getNumberOfColumns() + return variants.size / column + if (variants.size % column == 0) 0 else 1 + } + + override fun getNumberOfColumns(): Int { + return minOf(FLAT_COLUMN_MAX_COUNT, template[0].size) + } + + companion object { + private const val FLAT_COLUMN_MAX_COUNT = 6 + } +} diff --git a/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupMultiSkintoneDesign.kt b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupMultiSkintoneDesign.kt new file mode 100644 index 000000000..2dab8179d --- /dev/null +++ b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupMultiSkintoneDesign.kt @@ -0,0 +1,401 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.rishabh.emojipicker + +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.Color +import android.graphics.drawable.Drawable +import android.util.Log +import android.view.ContextThemeWrapper +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.FrameLayout +import android.widget.ImageView +import android.widget.LinearLayout +import androidx.annotation.StringRes +import androidx.core.content.res.ResourcesCompat +import com.google.firebase.crashlytics.buildtools.reloc.com.google.common.collect.ImmutableMap +import com.google.firebase.crashlytics.buildtools.reloc.com.google.common.primitives.ImmutableIntArray + + +/** Emoji picker popup with multi-skintone selection panel. */ +internal class EmojiPickerPopupMultiSkintoneDesign( + override val context: Context, + override val targetEmojiView: View, + override val variants: List, + override val popupView: LinearLayout, + override val emojiViewOnClickListener: View.OnClickListener, + targetEmoji: String +) : EmojiPickerPopupDesign() { + + private val inflater = LayoutInflater.from(context) + private val resultRow = + LinearLayout(context).apply { + orientation = LinearLayout.HORIZONTAL + layoutParams = + LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + } + + private var selectedLeftSkintone = -1 + private var selectedRightSkintone = -1 + + init { + val triggerVariantIndex: Int = variants.indexOf(targetEmoji) + if (triggerVariantIndex > 0) { + selectedLeftSkintone = (triggerVariantIndex - 1) / getNumberOfColumns() + selectedRightSkintone = + triggerVariantIndex - selectedLeftSkintone * getNumberOfColumns() - 1 + } + } + + override fun addRowsToPopupView() { + for (row in 0 until getActualNumberOfRows()) { + val rowLayout = + LinearLayout(context).apply { + orientation = LinearLayout.HORIZONTAL + layoutParams = + LinearLayout.LayoutParams( + FrameLayout.LayoutParams.WRAP_CONTENT, + FrameLayout.LayoutParams.WRAP_CONTENT + ) + } + for (column in 0 until getNumberOfColumns()) { + inflater.inflate(R.layout.emoji_picker_popup_image_view, rowLayout) + val imageView = rowLayout.getChildAt(column) as ImageView + imageView.apply { + layoutParams = + LinearLayout.LayoutParams(targetEmojiView.width, targetEmojiView.height) + isClickable = true + contentDescription = getImageContentDescription(context, row, column) + if ( + (hasLeftSkintone() && row == 0 && selectedLeftSkintone == column) || + (hasRightSkintone() && row == 1 && selectedRightSkintone == column) + ) { + isSelected = true + isClickable = false + } + setImageDrawable(getDrawableRes(context, row, column)) + setOnClickListener { + var unSelectedView: View? = null + if (row == 0) { + if (hasLeftSkintone()) { + unSelectedView = rowLayout.getChildAt(selectedLeftSkintone) + } + selectedLeftSkintone = column + } else { + if (hasRightSkintone()) { + unSelectedView = rowLayout.getChildAt(selectedRightSkintone) + } + selectedRightSkintone = column + } + if (unSelectedView != null) { + unSelectedView.isSelected = false + unSelectedView.isClickable = true + } + isClickable = false + isSelected = true + processResultView() + } + } + } + popupView.addView(rowLayout) + } + } + + private fun processResultView() { + val childCount = resultRow.childCount + if (childCount < 1 || childCount > 2) { + Log.e(TAG, "processResultEmojiForRectangleLayout(): unexpected emoji result row size") + return + } + // Remove the result emoji if it's already available. It will be available after the row is + // inflated the first time. + if (childCount == 2) { + resultRow.removeViewAt(1) + } + if (hasLeftSkintone() && hasRightSkintone()) { + inflater.inflate(R.layout.emoji_picker_popup_emoji_view, resultRow) + val layout = resultRow.getChildAt(1) as LinearLayout + layout.findViewById(R.id.emoji_picker_popup_emoji_view).apply { + willDrawVariantIndicator = false + isClickable = true + emoji = + variants[ + selectedLeftSkintone * getNumberOfColumns() + selectedRightSkintone + 1] + setOnClickListener(emojiViewOnClickListener) + layoutParams = + LinearLayout.LayoutParams(targetEmojiView.width, targetEmojiView.height) + } + layout.findViewById(R.id.emoji_picker_popup_emoji_view_wrapper).apply { + layoutParams = + LinearLayout.LayoutParams( + targetEmojiView.width * getNumberOfColumns() / 2, + targetEmojiView.height + ) + } + } else if (hasLeftSkintone()) { + drawImageView( + /* row= */ 0, + /*column=*/ selectedLeftSkintone, + /* applyGrayTint= */ false + ) + } else if (hasRightSkintone()) { + drawImageView( + /* row= */ 1, + /*column=*/ selectedRightSkintone, + /* applyGrayTint= */ false + ) + } else { + drawImageView(/* row= */ 0, /* column= */ 0, /* applyGrayTint= */ true) + } + } + + private fun drawImageView(row: Int, column: Int, applyGrayTint: Boolean) { + inflater + .inflate(R.layout.emoji_picker_popup_image_view, resultRow) + .findViewById(R.id.emoji_picker_popup_image_view) + .apply { + layoutParams = LinearLayout.LayoutParams(0, targetEmojiView.height, 1f) + setImageDrawable(getDrawableRes(context, row, column)) + if (applyGrayTint) { + imageTintList = ColorStateList.valueOf(Color.GRAY) + } + + var contentDescriptionRow = selectedLeftSkintone + var contentDescriptionColumn = selectedRightSkintone + if (hasLeftSkintone()) { + contentDescriptionRow = 0 + contentDescriptionColumn = selectedLeftSkintone + } else if (hasRightSkintone()) { + contentDescriptionRow = 1 + contentDescriptionColumn = selectedRightSkintone + } + contentDescription = + getImageContentDescription( + context, + contentDescriptionRow, + contentDescriptionColumn + ) + } + } + + override fun addLayoutFooter() { + inflater.inflate(R.layout.emoji_picker_popup_emoji_view, resultRow) + val layout = resultRow.getChildAt(0) as LinearLayout + layout.findViewById(R.id.emoji_picker_popup_emoji_view).apply { + willDrawVariantIndicator = false + emoji = variants[0] + layoutParams = LinearLayout.LayoutParams(targetEmojiView.width, targetEmojiView.height) + isClickable = true + setOnClickListener(emojiViewOnClickListener) + } + layout.findViewById(R.id.emoji_picker_popup_emoji_view_wrapper).apply { + layoutParams = + LinearLayout.LayoutParams( + targetEmojiView.width * getNumberOfColumns() / 2, + targetEmojiView.height + ) + } + processResultView() + popupView.addView(resultRow) + } + + override fun getNumberOfRows(): Int { + // Add one extra row for the neutral skin tone combination + return LAYOUT_ROWS + 1 + } + + override fun getNumberOfColumns(): Int { + return LAYOUT_COLUMNS + } + + private fun getActualNumberOfRows(): Int { + return LAYOUT_ROWS + } + + private fun hasLeftSkintone(): Boolean { + return selectedLeftSkintone != -1 + } + + private fun hasRightSkintone(): Boolean { + return selectedRightSkintone != -1 + } + + private fun getDrawableRes(context: Context, row: Int, column: Int): Drawable? { + val resArray: ImmutableIntArray? = SKIN_TONES_EMOJI_TO_RESOURCES[variants[0]] + if (resArray != null) { + val contextThemeWrapper = ContextThemeWrapper(context, VARIANT_STYLES[column]) + return ResourcesCompat.getDrawable( + context.resources, + resArray[row], + contextThemeWrapper.getTheme() + ) + } + return null + } + + private fun getImageContentDescription(context: Context, row: Int, column: Int): String { + return context.getString( + R.string.emoji_variant_content_desc_template, + context.getString(getSkintoneStringRes(/* isLeft= */ true, row, column)), + context.getString(getSkintoneStringRes(/* isLeft= */ false, row, column)) + ) + } + + @StringRes + private fun getSkintoneStringRes(isLeft: Boolean, row: Int, column: Int): Int { + // When there is no column, the selected position -1 will be passed in as column. + if (column == -1) { + return R.string.emoji_skin_tone_shadow_content_desc + } + return if (isLeft) { + if (row == 0) SKIN_TONE_CONTENT_DESC_RES_IDS[column] + else R.string.emoji_skin_tone_shadow_content_desc + } else { + if (row == 0) R.string.emoji_skin_tone_shadow_content_desc + else SKIN_TONE_CONTENT_DESC_RES_IDS[column] + } + } + + companion object { + private const val TAG = "MultiSkintoneDesign" + private const val LAYOUT_ROWS = 2 + private const val LAYOUT_COLUMNS = 5 + + private val SKIN_TONE_CONTENT_DESC_RES_IDS = + ImmutableIntArray.of( + R.string.emoji_skin_tone_light_content_desc, + R.string.emoji_skin_tone_medium_light_content_desc, + R.string.emoji_skin_tone_medium_content_desc, + R.string.emoji_skin_tone_medium_dark_content_desc, + R.string.emoji_skin_tone_dark_content_desc + ) + + private val VARIANT_STYLES = + ImmutableIntArray.of( + R.style.EmojiSkintoneSelectorLight, + R.style.EmojiSkintoneSelectorMediumLight, + R.style.EmojiSkintoneSelectorMedium, + R.style.EmojiSkintoneSelectorMediumDark, + R.style.EmojiSkintoneSelectorDark + ) + + /** + * Map from emoji that use the square layout strategy with skin tone swatches or rectangle + * strategy to their resources. + */ + private val SKIN_TONES_EMOJI_TO_RESOURCES = + ImmutableMap.Builder() + .put( + "🤝", + ImmutableIntArray.of( + R.drawable.handshake_skintone_shadow, + R.drawable.handshake_shadow_skintone + ) + ) + .put( + "👭", + ImmutableIntArray.of( + R.drawable.holding_women_skintone_shadow, + R.drawable.holding_women_shadow_skintone + ) + ) + .put( + "👫", + ImmutableIntArray.of( + R.drawable.holding_woman_man_skintone_shadow, + R.drawable.holding_woman_man_shadow_skintone + ) + ) + .put( + "👬", + ImmutableIntArray.of( + R.drawable.holding_men_skintone_shadow, + R.drawable.holding_men_shadow_skintone + ) + ) + .put( + "🧑‍🤝‍🧑", + ImmutableIntArray.of( + R.drawable.holding_people_skintone_shadow, + R.drawable.holding_people_shadow_skintone + ) + ) + .put( + "💏", + ImmutableIntArray.of( + R.drawable.kiss_people_skintone_shadow, + R.drawable.kiss_people_shadow_skintone + ) + ) + .put( + "👩‍❤️‍💋‍👨", + ImmutableIntArray.of( + R.drawable.kiss_woman_man_skintone_shadow, + R.drawable.kiss_woman_man_shadow_skintone + ) + ) + .put( + "👨‍❤️‍💋‍👨", + ImmutableIntArray.of( + R.drawable.kiss_men_skintone_shadow, + R.drawable.kiss_men_shadow_skintone + ) + ) + .put( + "👩‍❤️‍💋‍👩", + ImmutableIntArray.of( + R.drawable.kiss_women_skintone_shadow, + R.drawable.kiss_women_shadow_skintone + ) + ) + .put( + "💑", + ImmutableIntArray.of( + R.drawable.couple_heart_people_skintone_shadow, + R.drawable.couple_heart_people_shadow_skintone + ) + ) + .put( + "👩‍❤️‍👨", + ImmutableIntArray.of( + R.drawable.couple_heart_woman_man_skintone_shadow, + R.drawable.couple_heart_woman_man_shadow_skintone + ) + ) + .put( + "👨‍❤️‍👨", + ImmutableIntArray.of( + R.drawable.couple_heart_men_skintone_shadow, + R.drawable.couple_heart_men_shadow_skintone + ) + ) + .put( + "👩‍❤️‍👩", + ImmutableIntArray.of( + R.drawable.couple_heart_women_skintone_shadow, + R.drawable.couple_heart_women_shadow_skintone + ) + ) + .build() + } +} diff --git a/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupSquareDesign.kt b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupSquareDesign.kt new file mode 100644 index 000000000..0472995f0 --- /dev/null +++ b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupSquareDesign.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.rishabh.emojipicker + +import android.content.Context +import android.view.View +import android.widget.LinearLayout + +/** Emoji picker popup view with square design. */ +internal class EmojiPickerPopupSquareDesign( + override val context: Context, + override val targetEmojiView: View, + override val variants: List, + override val popupView: LinearLayout, + override val emojiViewOnClickListener: View.OnClickListener +) : EmojiPickerPopupDesign() { + init { + template = SQUARE_LAYOUT_TEMPLATE + } + + override fun getNumberOfRows(): Int { + return SQUARE_LAYOUT_TEMPLATE.size + } + + override fun getNumberOfColumns(): Int { + return SQUARE_LAYOUT_TEMPLATE[0].size + } + + companion object { + /** + * Square variant layout template without skin tone. 0 : a place holder Positive number is + * the index + 1 in the variant array + */ + private val SQUARE_LAYOUT_TEMPLATE = + arrayOf( + intArrayOf(0, 2, 3, 4, 5, 6), + intArrayOf(0, 7, 8, 9, 10, 11), + intArrayOf(0, 12, 13, 14, 15, 16), + intArrayOf(0, 17, 18, 19, 20, 21), + intArrayOf(1, 22, 23, 24, 25, 26) + ) + } +} diff --git a/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupView.kt b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupView.kt new file mode 100644 index 000000000..a6ca815f7 --- /dev/null +++ b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupView.kt @@ -0,0 +1,134 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.rishabh.emojipicker + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import android.widget.FrameLayout +import android.widget.LinearLayout + +/** Popup view for emoji picker to show emoji variants. */ +internal class EmojiPickerPopupView +@JvmOverloads +constructor( + context: Context, + attrs: AttributeSet?, + defStyleAttr: Int = 0, + private val targetEmojiView: View, + private val targetEmojiItem: EmojiViewItem, + private val emojiViewOnClickListener: OnClickListener +) : FrameLayout(context, attrs, defStyleAttr) { + + private val variants = targetEmojiItem.variants + private val targetEmoji = targetEmojiItem.emoji + private val popupView: LinearLayout + private val popupDesign: EmojiPickerPopupDesign + + init { + popupView = + inflate(context, R.layout.variant_popup, /* root= */ null) + .findViewById(R.id.variant_popup) + val layout = getLayout() + popupDesign = + when (layout) { + Layout.FLAT -> + EmojiPickerPopupFlatDesign( + context, + targetEmojiView, + variants, + popupView, + emojiViewOnClickListener + ) + Layout.SQUARE -> + EmojiPickerPopupSquareDesign( + context, + targetEmojiView, + variants, + popupView, + emojiViewOnClickListener + ) + Layout.SQUARE_WITH_SKIN_TONE_CIRCLE -> + EmojiPickerPopupMultiSkintoneDesign( + context, + targetEmojiView, + variants, + popupView, + emojiViewOnClickListener, + targetEmoji + ) + Layout.BIDIRECTIONAL -> + EmojiPickerPopupBidirectionalDesign( + context, + targetEmojiView, + variants, + popupView, + emojiViewOnClickListener + ) + } + popupDesign.addLayoutHeader() + popupDesign.addRowsToPopupView() + popupDesign.addLayoutFooter() + addView(popupView) + } + + fun getPopupViewWidth(): Int { + return popupDesign.getNumberOfColumns() * targetEmojiView.width + + popupView.paddingStart + + popupView.paddingEnd + } + + fun getPopupViewHeight(): Int { + return popupDesign.getNumberOfRows() * targetEmojiView.height + + popupView.paddingTop + + popupView.paddingBottom + } + + private fun getLayout(): Layout { + if (variants.size == SQUARE_LAYOUT_VARIANT_COUNT) + if (SQUARE_LAYOUT_EMOJI_NO_SKIN_TONE.contains(variants[0])) return Layout.SQUARE + else return Layout.SQUARE_WITH_SKIN_TONE_CIRCLE + else if (variants.size == BIDIRECTIONAL_VARIANTS_COUNT) return Layout.BIDIRECTIONAL + else return Layout.FLAT + } + + companion object { + private enum class Layout { + FLAT, + SQUARE, + SQUARE_WITH_SKIN_TONE_CIRCLE, + BIDIRECTIONAL + } + + /** + * The number of variants expected when using a square layout strategy. Square layouts are + * comprised of a 5x5 grid + the base variant. + */ + private const val SQUARE_LAYOUT_VARIANT_COUNT = 26 + + /** + * The number of variants expected when using a bidirectional layout strategy. Bidirectional + * layouts are comprised of bidirectional icon and a 3x6 grid with left direction emojis as + * default. After clicking the bidirectional icon, it switches to a bidirectional icon and a + * 3x6 grid with right direction emojis. + */ + private const val BIDIRECTIONAL_VARIANTS_COUNT = 36 + + // Set of emojis that use the square layout without skin tone swatches. + private val SQUARE_LAYOUT_EMOJI_NO_SKIN_TONE = setOf("👪") + } +} diff --git a/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupViewController.kt b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupViewController.kt new file mode 100644 index 000000000..36c4d76cb --- /dev/null +++ b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerPopupViewController.kt @@ -0,0 +1,70 @@ +package com.rishabh.emojipicker + + + +import android.content.Context +import android.view.Gravity +import android.view.View +import android.view.ViewGroup.LayoutParams +import android.view.WindowManager +import android.widget.PopupWindow +import android.widget.Toast +import kotlin.math.roundToInt + +/** + * Default controller class for emoji picker popup view. + * + *

Shows the popup view above the target Emoji. View under control is a {@code + * EmojiPickerPopupView}. + */ +internal class EmojiPickerPopupViewController( + private val context: Context, + private val emojiPickerPopupView: EmojiPickerPopupView, + private val clickedEmojiView: View +) { + private val popupWindow: PopupWindow = + PopupWindow( + emojiPickerPopupView, + LayoutParams.WRAP_CONTENT, + LayoutParams.WRAP_CONTENT, + /* focusable= */ false + ) + + fun show() { + popupWindow.apply { + val location = IntArray(2) + clickedEmojiView.getLocationInWindow(location) + // Make the popup view center align with the target emoji view. + val x = + location[0] + clickedEmojiView.width / 2f - + emojiPickerPopupView.getPopupViewWidth() / 2f + val y = location[1] - emojiPickerPopupView.getPopupViewHeight() + // Set background drawable so that the popup window is dismissed properly when clicking + // outside / scrolling for API < 23. + setBackgroundDrawable(context.getDrawable(R.drawable.popup_view_rounded_background)) + isOutsideTouchable = true + isTouchable = true + animationStyle = R.style.VariantPopupAnimation + elevation = + clickedEmojiView.context.resources + .getDimensionPixelSize(R.dimen.emoji_picker_popup_view_elevation) + .toFloat() + try { + showAtLocation(clickedEmojiView, Gravity.NO_GRAVITY, x.roundToInt(), y) + } catch (e: WindowManager.BadTokenException) { + Toast.makeText( + context, + "Don't use EmojiPickerView inside a Popup", + Toast.LENGTH_LONG + ) + .show() + } + } + } + + fun dismiss() { + if (popupWindow.isShowing) { + popupWindow.dismiss() + } + } +} diff --git a/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerView.kt b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerView.kt new file mode 100644 index 000000000..230e07d97 --- /dev/null +++ b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerView.kt @@ -0,0 +1,516 @@ + + +package com.rishabh.emojipicker + +import android.content.Context +import android.content.res.TypedArray +import android.util.AttributeSet +import android.view.View +import android.view.ViewGroup +import android.widget.FrameLayout +import androidx.core.util.Consumer +import androidx.core.view.ViewCompat +import com.rishabh.emojipicker.EmojiPickerConstants.DEFAULT_MAX_RECENT_ITEM_ROWS +import androidx.emoji2.text.EmojiCompat +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView + +import kotlin.coroutines.EmptyCoroutineContext +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext + +/** + * The emoji picker view that provides up-to-date emojis in a vertical scrollable view with a + * clickable horizontal header. + */ +class EmojiPickerView +@JvmOverloads +constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 +) : + FrameLayout(context, attrs, defStyleAttr) { + + internal companion object { + internal var emojiCompatLoaded: Boolean = false + } + var emojiPickedFromSuggestion:EmojiPickedFromSuggestion?=null + + private var _emojiGridRows: Float? = null + /** + * The number of rows of the emoji picker. + * + * Optional field. If not set, the value will be calculated based on parent view height and + * [emojiGridColumns]. Float value indicates that the picker could display the last row + * partially, so the users get the idea that they can scroll down for more contents. + * + * @attr ref androidx.emoji2.emojipicker.R.styleable.EmojiPickerView_emojiGridRows + */ + var emojiGridRows: Float + get() = _emojiGridRows ?: -1F + set(value) { + _emojiGridRows = value.takeIf { it > 0 } + // Refresh when emojiGridRows is reset + if (isLaidOut) { + showEmojiPickerView() + } + } + + private var _usedInSearchResult:Boolean = false + /*it is used to show the all the emoji and their categories if it's false else- only show emoji that is match with the description text */ + var usedInSearchResult:Boolean + get() = _usedInSearchResult + set(value) { + _usedInSearchResult = value + } + + /** + * The number of columns of the emoji picker. + * + * Default value([EmojiPickerConstants.DEFAULT_BODY_COLUMNS]: 9) will be used if + * emojiGridColumns is set to non-positive value. + * + * @attr ref androidx.emoji2.emojipicker.R.styleable.EmojiPickerView_emojiGridColumns + */ + var emojiGridColumns: Int = EmojiPickerConstants.DEFAULT_BODY_COLUMNS + set(value) { + field = value.takeIf { it > 0 } ?: EmojiPickerConstants.DEFAULT_BODY_COLUMNS + // Refresh when emojiGridColumns is reset + if (isLaidOut) { + showEmojiPickerView() + } + } + + private val stickyVariantProvider = StickyVariantProvider(context) + private val scope = CoroutineScope(EmptyCoroutineContext) + + private var recentEmojiProvider: RecentEmojiProvider = DefaultRecentEmojiProvider(context) + private var recentNeedsRefreshing: Boolean = true + private val recentItems: MutableList = mutableListOf() + private lateinit var recentItemGroup: ItemGroup + + lateinit var emojiPickerItems: EmojiPickerItems + lateinit var bodyAdapter: EmojiPickerBodyAdapter + + private var onEmojiPickedListener: Consumer? = null + + init { + val typedArray: TypedArray = + context.obtainStyledAttributes(attrs, R.styleable.EmojiPickerView, 0, 0) + _emojiGridRows = + with(R.styleable.EmojiPickerView_emojiGridRows) { + if (typedArray.hasValue(this)) { + typedArray.getFloat(this, 0F) + } else null + } + emojiGridColumns = + typedArray.getInt( + R.styleable.EmojiPickerView_emojiGridColumns, + EmojiPickerConstants.DEFAULT_BODY_COLUMNS + ) + + usedInSearchResult = typedArray.getBoolean(R.styleable.EmojiPickerView_usedInSearchResult, false) + typedArray.recycle() + + if (EmojiCompat.isConfigured()) { + when (EmojiCompat.get().loadState) { + EmojiCompat.LOAD_STATE_SUCCEEDED -> emojiCompatLoaded = true + EmojiCompat.LOAD_STATE_LOADING, + EmojiCompat.LOAD_STATE_DEFAULT -> + EmojiCompat.get() + .registerInitCallback( + object : EmojiCompat.InitCallback() { + override fun onInitialized() { + emojiCompatLoaded = true + scope.launch(Dispatchers.IO) { + BundledEmojiListLoader.load(context) + withContext(Dispatchers.Main) { + emojiPickerItems = buildEmojiPickerItems() + bodyAdapter.notifyDataSetChanged() + } + } + } + + override fun onFailed(throwable: Throwable?) {} + } + ) + } + } + scope.launch(Dispatchers.IO) { + val load = launch { BundledEmojiListLoader.load(context) } + refreshRecent() + load.join() + + withContext(Dispatchers.Main) { showEmojiPickerView() } + } + + + } + + public fun createEmojiPickerBodyAdapter(): EmojiPickerBodyAdapter { + return EmojiPickerBodyAdapter( + context, + emojiGridColumns, + _emojiGridRows, + stickyVariantProvider, + emojiPickerItemsProvider = { emojiPickerItems }, + onEmojiPickedListener = { emojiViewItem -> + emojiPickedFromSuggestion?.pickedEmoji(emojiViewItem.emoji) + emojiViewItem.emoji + onEmojiPickedListener?.accept(emojiViewItem) + recentEmojiProvider.recordSelection(emojiViewItem.emoji) + recentNeedsRefreshing = true + } + ) + } + + /*here is emoji is get from the bundle and send to recycler view*/ + fun buildEmojiPickerItems(onlyRecentEmojies: Boolean = false, description: String?=null ) :EmojiPickerItems{ + //used in search result usualy assign in the xml file when created a emojiPicker view + if(!usedInSearchResult){ + return EmojiPickerItems( + buildList { + add( + ItemGroup( + R.drawable.quantum_gm_ic_access_time_filled_vd_theme_24, + CategoryTitle(context.getString(R.string.emoji_category_recent)), + recentItems, + maxContentItemCount = DEFAULT_MAX_RECENT_ITEM_ROWS * emojiGridColumns, + emptyPlaceholderItem = + PlaceholderText( + context.getString(R.string.emoji_empty_recent_category) + ) + ) + .also { recentItemGroup = it } + ) + + for ((i, category) in + BundledEmojiListLoader.getCategorizedEmojiData().withIndex()) { + add( + ItemGroup( + category.headerIconId, + CategoryTitle(category.categoryName), + category.emojiDataList.mapIndexed { j, emojiData -> + + EmojiViewData( + stickyVariantProvider[emojiData.emoji], + dataIndex = i + j + ) + }, + ) + ) + } + } + ) + }else{ + if(onlyRecentEmojies && description==null){ + return EmojiPickerItems( + buildList { + add( + ItemGroup( + R.drawable.quantum_gm_ic_access_time_filled_vd_theme_24, + CategoryTitle(context.getString(R.string.emoji_category_recent)), + recentItems, + maxContentItemCount = DEFAULT_MAX_RECENT_ITEM_ROWS * emojiGridColumns, + emptyPlaceholderItem = + PlaceholderText( + context.getString(R.string.emoji_empty_recent_category) + ) + ) + .also { recentItemGroup = it } + ) + + } + ) + } + else if(!onlyRecentEmojies && description!=null){ + + return EmojiPickerItems( + buildList { + val listOfEmojiData = mutableListOf() + var categoryHeaderIconId:Int = 0 + var categoryName:String = "" + + for ((i, category) in BundledEmojiListLoader.getCategorizedEmojiData().withIndex()) { + for((j,emojiData) in category.emojiDataList.withIndex()){ + + if(emojiData.description.contains(description)){ + if(listOfEmojiData.size<17){ + categoryHeaderIconId = category.headerIconId + listOfEmojiData.add(EmojiViewData(stickyVariantProvider[emojiData.emoji], dataIndex = i + j)) + } + + } + } + } + add(ItemGroup(categoryHeaderIconId, + CategoryTitle(categoryName),listOfEmojiData) + ) + }) + }else { return EmojiPickerItems(listOf()) } + + } + + } + + private fun showEmojiPickerView() { + emojiPickerItems = buildEmojiPickerItems() + + val bodyLayoutManager = + GridLayoutManager(context, emojiGridColumns, LinearLayoutManager.VERTICAL,/* reverseLayout = */ false).apply { + spanSizeLookup = + object : GridLayoutManager.SpanSizeLookup() { + override fun getSpanSize(position: Int): Int { + return when (emojiPickerItems.getBodyItem(position).itemType) { + ItemType.CATEGORY_TITLE, + ItemType.PLACEHOLDER_TEXT -> emojiGridColumns + else -> 1 + } + } + } + } + + val headerAdapter = + EmojiPickerHeaderAdapter(context, emojiPickerItems, onHeaderIconClicked = + { with(emojiPickerItems.firstItemPositionByGroupIndex(it)) { + if (this == emojiPickerItems.groupRange(recentItemGroup).first) { + scope.launch { refreshRecent() } + } + bodyLayoutManager.scrollToPositionWithOffset(this, 0) + // The scroll position change will not be reflected until the next layout + // call, + // so force a new layout call here. + invalidate() + } + } + ) + + + // clear view's children in case of resetting layout + super.removeAllViews() + with(inflate(context, R.layout.emoji_picker, this)) { + // set headerView + ViewCompat.requireViewById(this, R.id.emoji_picker_header).apply { + if(usedInSearchResult){ + visibility = GONE + } + + layoutManager = object : LinearLayoutManager(context, HORIZONTAL, /* reverseLayout= */ false) { + override fun checkLayoutParams(lp: RecyclerView.LayoutParams): Boolean { + lp.width = (width - paddingStart - paddingEnd) / emojiPickerItems.numGroups + return true + } + } + adapter = headerAdapter + } + + // set bodyView + ViewCompat.requireViewById(this, R.id.emoji_picker_body).apply { + + layoutManager = bodyLayoutManager + adapter = createEmojiPickerBodyAdapter() + .apply { setHasStableIds(true) } + .also { bodyAdapter = it } + + if(!usedInSearchResult){ + addOnScrollListener(object : RecyclerView.OnScrollListener() { + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + super.onScrolled(recyclerView, dx, dy) + headerAdapter.selectedGroupIndex = emojiPickerItems.groupIndexByItemPosition( + bodyLayoutManager.findFirstCompletelyVisibleItemPosition() + ) + if (recentNeedsRefreshing && + bodyLayoutManager.findFirstVisibleItemPosition() !in emojiPickerItems.groupRange(recentItemGroup) + ) { + scope.launch { refreshRecent() } + } + } + } + ) + } + + // Disable item insertion/deletion animation. This keeps view holder unchanged when + // item updates. + itemAnimator = null + setRecycledViewPool( + RecyclerView.RecycledViewPool().apply { + setMaxRecycledViews( + ItemType.EMOJI.ordinal, + EmojiPickerConstants.EMOJI_VIEW_POOL_SIZE + ) + } + ) + } + } + } + + internal suspend fun refreshRecent() { + if (!recentNeedsRefreshing) { + return + } + val oldGroupSize = if (::recentItemGroup.isInitialized) recentItemGroup.size else 0 + val recent = recentEmojiProvider.getRecentEmojiList() + withContext(Dispatchers.Main) { + recentItems.clear() + recentItems.addAll( + recent.map { + EmojiViewData( + it, + updateToSticky = false, + ) + } + ) + if (::emojiPickerItems.isInitialized) { + val range = emojiPickerItems.groupRange(recentItemGroup) + if (recentItemGroup.size > oldGroupSize) { + bodyAdapter.notifyItemRangeInserted( + range.first + oldGroupSize, + recentItemGroup.size - oldGroupSize + ) + } else if (recentItemGroup.size < oldGroupSize) { + bodyAdapter.notifyItemRangeRemoved( + range.first + recentItemGroup.size, + oldGroupSize - recentItemGroup.size + ) + } + bodyAdapter.notifyItemRangeChanged( + range.first, + minOf(oldGroupSize, recentItemGroup.size) + ) + recentNeedsRefreshing = false + } + } + } + + /** + * This function is used to set the custom behavior after clicking on an emoji icon. Clients + * could specify their own behavior inside this function. + */ + fun setOnEmojiPickedListener(onEmojiPickedListener: Consumer?) { + this.onEmojiPickedListener = onEmojiPickedListener + } + + fun setRecentEmojiProvider(recentEmojiProvider: RecentEmojiProvider) { + this.recentEmojiProvider = recentEmojiProvider + scope.launch { + recentNeedsRefreshing = true + refreshRecent() + } + } + + /** + * The following functions disallow clients to add view to the EmojiPickerView + * + * @param child the child view to be added + * @throws UnsupportedOperationException + */ + override fun addView(child: View?) { + if (childCount > 0) + throw UnsupportedOperationException(EmojiPickerConstants.ADD_VIEW_EXCEPTION_MESSAGE) + else super.addView(child) + } + + /** + * @param child + * @param params + * @throws UnsupportedOperationException + */ + override fun addView(child: View?, params: ViewGroup.LayoutParams?) { + if (childCount > 0) + throw UnsupportedOperationException(EmojiPickerConstants.ADD_VIEW_EXCEPTION_MESSAGE) + else super.addView(child, params) + } + + /** + * @param child + * @param index + * @throws UnsupportedOperationException + */ + override fun addView(child: View?, index: Int) { + if (childCount > 0) + throw UnsupportedOperationException(EmojiPickerConstants.ADD_VIEW_EXCEPTION_MESSAGE) + else super.addView(child, index) + } + + /** + * @param child + * @param index + * @param params + * @throws UnsupportedOperationException + */ + override fun addView(child: View?, index: Int, params: ViewGroup.LayoutParams?) { + if (childCount > 0) + throw UnsupportedOperationException(EmojiPickerConstants.ADD_VIEW_EXCEPTION_MESSAGE) + else super.addView(child, index, params) + } + + /** + * @param child + * @param width + * @param height + * @throws UnsupportedOperationException + */ + override fun addView(child: View?, width: Int, height: Int) { + if (childCount > 0) + throw UnsupportedOperationException(EmojiPickerConstants.ADD_VIEW_EXCEPTION_MESSAGE) + else super.addView(child, width, height) + } + + /** + * The following functions disallow clients to remove view from the EmojiPickerView + * + * @throws UnsupportedOperationException + */ + override fun removeAllViews() { + throw UnsupportedOperationException(EmojiPickerConstants.REMOVE_VIEW_EXCEPTION_MESSAGE) + } + + /** + * @param child + * @throws UnsupportedOperationException + */ + override fun removeView(child: View?) { + throw UnsupportedOperationException(EmojiPickerConstants.REMOVE_VIEW_EXCEPTION_MESSAGE) + } + + /** + * @param index + * @throws UnsupportedOperationException + */ + override fun removeViewAt(index: Int) { + throw UnsupportedOperationException(EmojiPickerConstants.REMOVE_VIEW_EXCEPTION_MESSAGE) + } + + /** + * @param child + * @throws UnsupportedOperationException + */ + override fun removeViewInLayout(child: View?) { + throw UnsupportedOperationException(EmojiPickerConstants.REMOVE_VIEW_EXCEPTION_MESSAGE) + } + + /** + * @param start + * @param count + * @throws UnsupportedOperationException + */ + override fun removeViews(start: Int, count: Int) { + throw UnsupportedOperationException(EmojiPickerConstants.REMOVE_VIEW_EXCEPTION_MESSAGE) + } + + /** + * @param start + * @param count + * @throws UnsupportedOperationException + */ + override fun removeViewsInLayout(start: Int, count: Int) { + throw UnsupportedOperationException(EmojiPickerConstants.REMOVE_VIEW_EXCEPTION_MESSAGE) + } + + + + interface EmojiPickedFromSuggestion { + fun pickedEmoji(emoji:String) + } +} diff --git a/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiView.kt b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiView.kt new file mode 100644 index 000000000..835881ae8 --- /dev/null +++ b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiView.kt @@ -0,0 +1,173 @@ + + +package com.rishabh.emojipicker + +import android.content.Context +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.graphics.Rect +import android.os.Build +import android.text.Layout +import android.text.Spanned +import android.text.StaticLayout +import android.text.TextPaint +import android.util.AttributeSet +import android.util.TypedValue +import android.view.View +import androidx.annotation.RequiresApi +import androidx.core.graphics.applyCanvas +import androidx.emoji2.text.EmojiCompat + +/** A customized view to support drawing emojis asynchronously. */ +internal class EmojiView +@JvmOverloads +constructor( + context: Context, + attrs: AttributeSet? = null, +) : View(context, attrs) { + + companion object { + private const val EMOJI_DRAW_TEXT_SIZE_SP = 30 + } + + init { + background = context.getDrawable(R.drawable.ripple_emoji_view) + importantForAccessibility = IMPORTANT_FOR_ACCESSIBILITY_YES + } + + internal var willDrawVariantIndicator: Boolean = true + + private val textPaint = + TextPaint(Paint.ANTI_ALIAS_FLAG or Paint.FILTER_BITMAP_FLAG).apply { + textSize = + TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_SP, + EMOJI_DRAW_TEXT_SIZE_SP.toFloat(), + context.resources.displayMetrics + ) + } + + private val offscreenCanvasBitmap: Bitmap = + with(textPaint.fontMetricsInt) { + val size = bottom - top + Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888) + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + val size = + minOf(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec)) - + context.resources.getDimensionPixelSize(R.dimen.emoji_picker_emoji_view_padding) + setMeasuredDimension(size, size) + } + + override fun draw(canvas: Canvas) { + super.draw(canvas) + canvas.run { + save() + scale( + width.toFloat() / offscreenCanvasBitmap.width, + height.toFloat() / offscreenCanvasBitmap.height + ) + drawBitmap(offscreenCanvasBitmap, 0f, 0f, null) + restore() + } + } + + var emoji: CharSequence? = null + set(value) { + field = value + post { + if (value != null) { + if (value == this.emoji) { + drawEmoji( + if (EmojiPickerView.emojiCompatLoaded) + EmojiCompat.get().process(value) ?: value + else value, + drawVariantIndicator = + willDrawVariantIndicator && + BundledEmojiListLoader.getEmojiVariantsLookup() + .containsKey(value) + ) + contentDescription = value + } + invalidate() + } else { + offscreenCanvasBitmap.eraseColor(Color.TRANSPARENT) + } + } + } + + private fun drawEmoji(emoji: CharSequence, drawVariantIndicator: Boolean) { + offscreenCanvasBitmap.eraseColor(Color.TRANSPARENT) + offscreenCanvasBitmap.applyCanvas { + if (emoji is Spanned) { + createStaticLayout(emoji, width).draw(this) + } else { + val textWidth = textPaint.measureText(emoji, 0, emoji.length) + drawText( + emoji, + /* start = */ 0, + /* end = */ emoji.length, + /* x = */ (width - textWidth) / 2, + /* y = */ -textPaint.fontMetrics.top, + textPaint, + ) + } + if (drawVariantIndicator) { + context + .getDrawable(R.drawable.variant_availability_indicator) + ?.apply { + val canvasWidth = this@applyCanvas.width + val canvasHeight = this@applyCanvas.height + val indicatorWidth = + context.resources.getDimensionPixelSize( + R.dimen.variant_availability_indicator_width + ) + val indicatorHeight = + context.resources.getDimensionPixelSize( + R.dimen.variant_availability_indicator_height + ) + bounds = + Rect( + canvasWidth - indicatorWidth, + canvasHeight - indicatorHeight, + canvasWidth, + canvasHeight + ) + }!! + .draw(this) + } + } + } + + @RequiresApi(23) + internal object Api23Impl { + fun createStaticLayout(emoji: Spanned, textPaint: TextPaint, width: Int): StaticLayout = + StaticLayout.Builder.obtain(emoji, 0, emoji.length, textPaint, width) + .apply { + setAlignment(Layout.Alignment.ALIGN_CENTER) + setLineSpacing(/* spacingAdd= */ 0f, /* spacingMult= */ 1f) + setIncludePad(false) + } + .build() + } + + private fun createStaticLayout(emoji: Spanned, width: Int): StaticLayout { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + return Api23Impl.createStaticLayout(emoji, textPaint, width) + } else { + @Suppress("DEPRECATION") + return StaticLayout( + emoji, + textPaint, + width, + Layout.Alignment.ALIGN_CENTER, + /* spacingmult = */ 1f, + /* spacingadd = */ 0f, + /* includepad = */ false, + ) + } + } +} diff --git a/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiViewHolder.kt b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiViewHolder.kt new file mode 100644 index 000000000..95462b383 --- /dev/null +++ b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiViewHolder.kt @@ -0,0 +1,87 @@ + + +package com.rishabh.emojipicker + +import android.content.Context +import android.view.View +import android.view.View.OnLongClickListener +import android.view.ViewGroup.LayoutParams +import android.view.accessibility.AccessibilityEvent +import androidx.recyclerview.widget.RecyclerView.ViewHolder + +/** A [ViewHolder] containing an emoji view and emoji data. */ +internal class EmojiViewHolder( + context: Context, + width: Int, + height: Int, + private val stickyVariantProvider: StickyVariantProvider, + private val onEmojiPickedListener: EmojiViewHolder.(EmojiViewItem) -> Unit, + private val onEmojiPickedFromPopupListener: EmojiViewHolder.(String) -> Unit +) : ViewHolder(EmojiView(context)) { + + + private val onEmojiLongClickListener: OnLongClickListener = + OnLongClickListener { targetEmojiView -> + + showEmojiPopup(context, targetEmojiView) + } + + private val emojiView: EmojiView = + (itemView as EmojiView).apply { + layoutParams = LayoutParams(width, height) + isClickable = true + setOnClickListener { + it.sendAccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT) + onEmojiPickedListener(emojiViewItem) + } + } + private lateinit var emojiViewItem: EmojiViewItem + private lateinit var emojiPickerPopupViewController: EmojiPickerPopupViewController + + fun bindEmoji( + emoji: String, + ) { + emojiView.emoji = emoji + emojiViewItem = makeEmojiViewItem(emoji) + + if (emojiViewItem.variants.isNotEmpty()) { + emojiView.setOnLongClickListener(onEmojiLongClickListener) + emojiView.isLongClickable = true + } else { + + emojiView.setOnLongClickListener(null) + emojiView.isLongClickable = false + } + } + + private fun showEmojiPopup(context: Context, clickedEmojiView: View): Boolean { + val emojiPickerPopupView = + EmojiPickerPopupView( + context, + /* attrs= */ null, + targetEmojiView = clickedEmojiView, + targetEmojiItem = emojiViewItem, + emojiViewOnClickListener = { view -> + val emojiPickedInPopup = (view as EmojiView).emoji.toString() + onEmojiPickedFromPopupListener(emojiPickedInPopup) + onEmojiPickedListener(makeEmojiViewItem(emojiPickedInPopup)) + // variants[0] is always the base (i.e., primary) emoji + stickyVariantProvider.update(emojiViewItem.variants[0], emojiPickedInPopup) + emojiPickerPopupViewController.dismiss() + // Hover on the base emoji after popup dismissed + clickedEmojiView.sendAccessibilityEvent( + AccessibilityEvent.TYPE_VIEW_HOVER_ENTER + ) + } + ) + emojiPickerPopupViewController = + EmojiPickerPopupViewController(context, emojiPickerPopupView, clickedEmojiView) + emojiPickerPopupViewController.show() + return true + } + + private fun makeEmojiViewItem(emoji: String) = + + + EmojiViewItem(emoji, "",BundledEmojiListLoader.getEmojiVariantsLookup()[emoji] ?: listOf()) +} diff --git a/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiViewItem.kt b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiViewItem.kt new file mode 100644 index 000000000..07a1d78fa --- /dev/null +++ b/emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiViewItem.kt @@ -0,0 +1,11 @@ + + +package com.rishabh.emojipicker + +/** + * [EmojiViewItem] is a class holding the displayed emoji and its emoji variants + * + * @param emoji Used to represent the displayed emoji of the [EmojiViewItem]. + * @param variants Used to represent the corresponding emoji variants of this base emoji. + */ +class EmojiViewItem(val emoji: String, val description: String,val variants: List) diff --git a/emojipicker/src/main/java/androidx/emoji2/emojipicker/ItemViewData.kt b/emojipicker/src/main/java/androidx/emoji2/emojipicker/ItemViewData.kt new file mode 100644 index 000000000..d025a9925 --- /dev/null +++ b/emojipicker/src/main/java/androidx/emoji2/emojipicker/ItemViewData.kt @@ -0,0 +1,32 @@ + + +package com.rishabh.emojipicker + +enum class ItemType { + CATEGORY_TITLE, + PLACEHOLDER_TEXT, + EMOJI, +} + +/** Represents an item within the body RecyclerView. */ +sealed class ItemViewData(val itemType: ItemType) { + val viewType = itemType.ordinal +} + +/** Title of each category. */ +data class CategoryTitle(val title: String) : ItemViewData(ItemType.CATEGORY_TITLE) + +/** Text to display when the category contains no items. */ +data class PlaceholderText(val text: String) : ItemViewData(ItemType.PLACEHOLDER_TEXT) + +/** Represents an emoji. */ +data class EmojiViewData( + var emoji: String, + val updateToSticky: Boolean = true, + // Needed to ensure uniqueness since we enabled stable Id. + val dataIndex: Int = 0 +) : ItemViewData(ItemType.EMOJI) + +internal object Extensions { + internal fun Int.toItemType() = ItemType.values()[this] +} diff --git a/emojipicker/src/main/java/androidx/emoji2/emojipicker/RecentEmojiAsyncProvider.kt b/emojipicker/src/main/java/androidx/emoji2/emojipicker/RecentEmojiAsyncProvider.kt new file mode 100644 index 000000000..5f599e721 --- /dev/null +++ b/emojipicker/src/main/java/androidx/emoji2/emojipicker/RecentEmojiAsyncProvider.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.rishabh.emojipicker + +import com.google.common.util.concurrent.ListenableFuture +import kotlinx.coroutines.guava.await + +/** + * A interface equivalent to [RecentEmojiProvider] that allows java clients to override the + * [ListenableFuture] based function [getRecentEmojiListAsync] in order to provide recent emojis. + */ +interface RecentEmojiAsyncProvider { + fun recordSelection(emoji: String) + + fun getRecentEmojiListAsync(): ListenableFuture> +} + +/** An adapter for the [RecentEmojiAsyncProvider]. */ +class RecentEmojiProviderAdapter(private val recentEmojiAsyncProvider: RecentEmojiAsyncProvider) : + RecentEmojiProvider { + override fun recordSelection(emoji: String) { + recentEmojiAsyncProvider.recordSelection(emoji) + } + + override suspend fun getRecentEmojiList() = + recentEmojiAsyncProvider.getRecentEmojiListAsync().await() +} diff --git a/emojipicker/src/main/java/androidx/emoji2/emojipicker/RecentEmojiProvider.kt b/emojipicker/src/main/java/androidx/emoji2/emojipicker/RecentEmojiProvider.kt new file mode 100644 index 000000000..8362822f9 --- /dev/null +++ b/emojipicker/src/main/java/androidx/emoji2/emojipicker/RecentEmojiProvider.kt @@ -0,0 +1,19 @@ + + +package com.rishabh.emojipicker + +/** An interface to provide recent emoji list. */ +interface RecentEmojiProvider { + /** + * Records an emoji into recent emoji list. This fun will be called when an emoji is selected. + * Clients could specify the behavior to record recently used emojis.(e.g. click frequency). + */ + fun recordSelection(emoji: String) + + /** + * Returns a list of recent emojis. Default behavior: The most recently used emojis will be + * displayed first. Clients could also specify the behavior such as displaying the emojis from + * high click frequency to low click frequency. + */ + suspend fun getRecentEmojiList(): List +} diff --git a/emojipicker/src/main/java/androidx/emoji2/emojipicker/StickyVariantProvider.kt b/emojipicker/src/main/java/androidx/emoji2/emojipicker/StickyVariantProvider.kt new file mode 100644 index 000000000..ae8094c1f --- /dev/null +++ b/emojipicker/src/main/java/androidx/emoji2/emojipicker/StickyVariantProvider.kt @@ -0,0 +1,53 @@ + + +package com.rishabh.emojipicker + +import android.content.Context +import android.content.Context.MODE_PRIVATE + +/** A class that handles user's emoji variant selection using SharedPreferences. + * or basically it saves emoji varient and changethe base emoji to that emoji varient next time */ +class StickyVariantProvider(context: Context) { + companion object { + const val PREFERENCES_FILE_NAME = "androidx.emoji2.emojipicker.preferences" + const val STICKY_VARIANT_PROVIDER_KEY = "pref_key_sticky_variant" + const val KEY_VALUE_DELIMITER = "=" + const val ENTRY_DELIMITER = "|" + } + + private val sharedPreferences = + context.getSharedPreferences(PREFERENCES_FILE_NAME, MODE_PRIVATE) + + private val stickyVariantMap: MutableMap by lazy { + sharedPreferences + .getString(STICKY_VARIANT_PROVIDER_KEY, null) + ?.split(ENTRY_DELIMITER) + ?.associate { entry -> + entry + .split(KEY_VALUE_DELIMITER, limit = 2) + .takeIf { it.size == 2 } + ?.let { it[0] to it[1] } ?: ("" to "") + } + ?.toMutableMap() ?: mutableMapOf() + } + + + + + + internal operator fun get(emoji: String): String = stickyVariantMap[emoji] ?: emoji + + internal fun update(baseEmoji: String, variantClicked: String) { + stickyVariantMap.apply { + if (baseEmoji == variantClicked) { + this.remove(baseEmoji) + } else { + this[baseEmoji] = variantClicked + } + sharedPreferences + .edit() + .putString(STICKY_VARIANT_PROVIDER_KEY, entries.joinToString(ENTRY_DELIMITER)) + .commit() + } + } +} diff --git a/emojipicker/src/main/java/androidx/emoji2/emojipicker/utils/FileCache.kt b/emojipicker/src/main/java/androidx/emoji2/emojipicker/utils/FileCache.kt new file mode 100644 index 000000000..87b5ab954 --- /dev/null +++ b/emojipicker/src/main/java/androidx/emoji2/emojipicker/utils/FileCache.kt @@ -0,0 +1,150 @@ + + +package com.rishabh.emojipicker.utils + +import android.content.Context +import android.content.pm.PackageManager +import android.os.Build +import android.util.Log +import androidx.annotation.GuardedBy +import androidx.annotation.RequiresApi +import androidx.annotation.VisibleForTesting +import androidx.core.content.ContextCompat +import com.rishabh.emojipicker.BundledEmojiListLoader +import com.rishabh.emojipicker.EmojiViewItem +import java.io.File +import java.io.IOException + +/** + * A class that manages cache files for the emoji picker. All cache files are stored in DE (Device + * Encryption) storage (N+), and will be invalidated if device OS version or App version is updated. + * + * Currently this class is only used by [BundledEmojiListLoader]. All renderable emojis will be + * cached by categories under /app.package.name/cache/emoji_picker/ + * /emoji.... + */ +internal class FileCache(context: Context) { + + @VisibleForTesting @GuardedBy("lock") internal val emojiPickerCacheDir: File + private val currentProperty: String + private val lock = Any() + + init { + val osVersion = "${Build.VERSION.SDK_INT}_${Build.TIME}" + val appVersion = getVersionCode(context) + currentProperty = "$osVersion.$appVersion" + emojiPickerCacheDir = + File(getDeviceProtectedStorageContext(context).cacheDir, EMOJI_PICKER_FOLDER) + if (!emojiPickerCacheDir.exists()) emojiPickerCacheDir.mkdir() + } + + /** Get cache for a given file name, or write to a new file using the [defaultValue] factory. */ + internal fun getOrPut( + key: String, + defaultValue: () -> List + ): List { + synchronized(lock) { + val targetDir = File(emojiPickerCacheDir, currentProperty) + Log.i("getCatcheclocation", targetDir.canonicalPath.toString()) + + // No matching cache folder for current property, clear stale cache directory if any + if (!targetDir.exists()) { + emojiPickerCacheDir.listFiles()?.forEach { it.deleteRecursively() } + targetDir.mkdirs() + } + + val targetFile = File(targetDir, key) + return readFrom(targetFile) ?: writeTo(targetFile, defaultValue) + } + } + + private fun readFrom(targetFile: File): List? { + if (!targetFile.isFile) return null + return targetFile + .bufferedReader() + .useLines { + + it.toList() } + .map { + Log.i("heheh", it.toString()) + it.split(",") } + .map { + Log.i("thisiswathigot", it.toString()) + val emoji = it.getOrNull(0) ?: "" + val description = it.getOrNull(1) ?:"" + + + EmojiViewItem(emoji, description,it.drop(2) ) + } + } + + private fun writeTo( + targetFile: File, + defaultValue: () -> List + ): List { + val data = defaultValue.invoke() + if (targetFile.exists()) { + if (!targetFile.delete()) { + Log.wtf(TAG, "Can't delete file: $targetFile") + } + } + if (!targetFile.createNewFile()) { + throw IOException("Can't create file: $targetFile") + } + targetFile.bufferedWriter().use { out -> + for (emoji in data) { + out.write(emoji.emoji) + out.write(",${emoji.description}") + + emoji.variants.forEach { out.write(",$it") } + out.newLine() + } + } + return data + } + + /** Returns a new [context] for accessing device protected storage. */ + private fun getDeviceProtectedStorageContext(context: Context) = + context.takeIf { ContextCompat.isDeviceProtectedStorage(it) } + ?: run { ContextCompat.createDeviceProtectedStorageContext(context) } + ?: context + + /** Gets the version code for a package. */ + @Suppress("DEPRECATION") + private fun getVersionCode(context: Context): Long = + try { + if (Build.VERSION.SDK_INT >= 33) Api33Impl.getAppVersionCode(context) + else if (Build.VERSION.SDK_INT >= 28) Api28Impl.getAppVersionCode(context) + else context.packageManager.getPackageInfo(context.packageName, 0).versionCode.toLong() + } catch (e: PackageManager.NameNotFoundException) { + // Default version to 1 + 1 + } + + companion object { + @Volatile private var instance: FileCache? = null + + internal fun getInstance(context: Context): FileCache = + instance ?: synchronized(this) { instance ?: FileCache(context).also { instance = it } } + + private const val EMOJI_PICKER_FOLDER = "emoji_picker" + private const val TAG = "emojipicker.FileCache" + } + + @RequiresApi(Build.VERSION_CODES.TIRAMISU) + internal object Api33Impl { + fun getAppVersionCode(context: Context) = + context.packageManager + .getPackageInfo(context.packageName, PackageManager.PackageInfoFlags.of(0)) + .longVersionCode + } + + @Suppress("DEPRECATION") + @RequiresApi(Build.VERSION_CODES.P) + internal object Api28Impl { + fun getAppVersionCode(context: Context) = + context.packageManager + .getPackageInfo(context.packageName, /* flags= */ 0) + .longVersionCode + } +} diff --git a/emojipicker/src/main/java/androidx/emoji2/emojipicker/utils/UnicodeRenderableManager.kt b/emojipicker/src/main/java/androidx/emoji2/emojipicker/utils/UnicodeRenderableManager.kt new file mode 100644 index 000000000..e2f14df73 --- /dev/null +++ b/emojipicker/src/main/java/androidx/emoji2/emojipicker/utils/UnicodeRenderableManager.kt @@ -0,0 +1,69 @@ + + +package com.rishabh.emojipicker.utils + +import android.os.Build +import android.text.TextPaint +import androidx.annotation.VisibleForTesting +import androidx.core.graphics.PaintCompat +import com.rishabh.emojipicker.EmojiPickerView +import androidx.emoji2.text.EmojiCompat + +/** Checks renderability of unicode characters. */ +internal object UnicodeRenderableManager { + + private const val VARIATION_SELECTOR = "\uFE0F" + + private const val YAWNING_FACE_EMOJI = "\uD83E\uDD71" + + private val paint = TextPaint() + + /** + * Some emojis were usual (non-emoji) characters. Old devices cannot render them with variation + * selector (U+FE0F) so it's worth trying to check renderability again without variation + * selector. + */ + private val CATEGORY_MOVED_EMOJIS = + listOf( // These three characters have been emoji since Unicode emoji version 4. + // version 3: https://unicode.org/Public/emoji/3.0/emoji-data.txt + // version 4: https://unicode.org/Public/emoji/4.0/emoji-data.txt + "\u2695\uFE0F", // STAFF OF AESCULAPIUS + "\u2640\uFE0F", // FEMALE SIGN + "\u2642\uFE0F", // MALE SIGN + // These three characters have been emoji since Unicode emoji version 11. + // version 5: https://unicode.org/Public/emoji/5.0/emoji-data.txt + // version 11: https://unicode.org/Public/emoji/11.0/emoji-data.txt + "\u265F\uFE0F", // BLACK_CHESS_PAWN + "\u267E\uFE0F" // PERMANENT_PAPER_SIGN + ) + + /** + * For a given emoji, check it's renderability with EmojiCompat if enabled. Otherwise, use + * [PaintCompat#hasGlyph]. + * + * Note: For older API version, codepoints {@code U+0xFE0F} are removed. + */ + internal fun isEmojiRenderable(emoji: String) = + if (EmojiPickerView.emojiCompatLoaded) + EmojiCompat.get().getEmojiMatch(emoji, Int.MAX_VALUE) == EmojiCompat.EMOJI_SUPPORTED + else getClosestRenderable(emoji) != null + + // Yawning face is added in emoji 12 which is the first version starts to support gender + // inclusive emojis. + internal fun isEmoji12Supported() = isEmojiRenderable(YAWNING_FACE_EMOJI) + + @VisibleForTesting + fun getClosestRenderable(emoji: String): String? { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + return emoji.replace(VARIATION_SELECTOR, "").takeIfHasGlyph() + } + return emoji.takeIfHasGlyph() + ?: run { + if (CATEGORY_MOVED_EMOJIS.contains(emoji)) + emoji.replace(VARIATION_SELECTOR, "").takeIfHasGlyph() + else null + } + } + + private fun String.takeIfHasGlyph() = takeIf { PaintCompat.hasGlyph(paint, this) } +} diff --git a/emojipicker/src/main/res/anim/slide_down_and_fade_out.xml b/emojipicker/src/main/res/anim/slide_down_and_fade_out.xml new file mode 100644 index 000000000..c25f30ddd --- /dev/null +++ b/emojipicker/src/main/res/anim/slide_down_and_fade_out.xml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/emojipicker/src/main/res/anim/slide_up_and_fade_in.xml b/emojipicker/src/main/res/anim/slide_up_and_fade_in.xml new file mode 100644 index 000000000..618b96e11 --- /dev/null +++ b/emojipicker/src/main/res/anim/slide_up_and_fade_in.xml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/emojipicker/src/main/res/drawable/couple_heart_men_shadow_skintone.xml b/emojipicker/src/main/res/drawable/couple_heart_men_shadow_skintone.xml new file mode 100644 index 000000000..e480cbf52 --- /dev/null +++ b/emojipicker/src/main/res/drawable/couple_heart_men_shadow_skintone.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/couple_heart_men_skintone_shadow.xml b/emojipicker/src/main/res/drawable/couple_heart_men_skintone_shadow.xml new file mode 100644 index 000000000..6d54233c9 --- /dev/null +++ b/emojipicker/src/main/res/drawable/couple_heart_men_skintone_shadow.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/couple_heart_people_shadow_skintone.xml b/emojipicker/src/main/res/drawable/couple_heart_people_shadow_skintone.xml new file mode 100644 index 000000000..219fb0aa5 --- /dev/null +++ b/emojipicker/src/main/res/drawable/couple_heart_people_shadow_skintone.xml @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/emojipicker/src/main/res/drawable/couple_heart_people_skintone_shadow.xml b/emojipicker/src/main/res/drawable/couple_heart_people_skintone_shadow.xml new file mode 100644 index 000000000..09e95e563 --- /dev/null +++ b/emojipicker/src/main/res/drawable/couple_heart_people_skintone_shadow.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/couple_heart_woman_man_shadow_skintone.xml b/emojipicker/src/main/res/drawable/couple_heart_woman_man_shadow_skintone.xml new file mode 100644 index 000000000..1107c60cf --- /dev/null +++ b/emojipicker/src/main/res/drawable/couple_heart_woman_man_shadow_skintone.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/couple_heart_woman_man_skintone_shadow.xml b/emojipicker/src/main/res/drawable/couple_heart_woman_man_skintone_shadow.xml new file mode 100644 index 000000000..1334b6771 --- /dev/null +++ b/emojipicker/src/main/res/drawable/couple_heart_woman_man_skintone_shadow.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/couple_heart_women_shadow_skintone.xml b/emojipicker/src/main/res/drawable/couple_heart_women_shadow_skintone.xml new file mode 100644 index 000000000..4fe76d7d1 --- /dev/null +++ b/emojipicker/src/main/res/drawable/couple_heart_women_shadow_skintone.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/couple_heart_women_skintone_shadow.xml b/emojipicker/src/main/res/drawable/couple_heart_women_skintone_shadow.xml new file mode 100644 index 000000000..b8b660094 --- /dev/null +++ b/emojipicker/src/main/res/drawable/couple_heart_women_skintone_shadow.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/gm_filled_emoji_emotions_vd_theme_24.xml b/emojipicker/src/main/res/drawable/gm_filled_emoji_emotions_vd_theme_24.xml new file mode 100644 index 000000000..cfdbdab52 --- /dev/null +++ b/emojipicker/src/main/res/drawable/gm_filled_emoji_emotions_vd_theme_24.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/emojipicker/src/main/res/drawable/gm_filled_emoji_events_vd_theme_24.xml b/emojipicker/src/main/res/drawable/gm_filled_emoji_events_vd_theme_24.xml new file mode 100644 index 000000000..f588bf36a --- /dev/null +++ b/emojipicker/src/main/res/drawable/gm_filled_emoji_events_vd_theme_24.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/emojipicker/src/main/res/drawable/gm_filled_emoji_food_beverage_vd_theme_24.xml b/emojipicker/src/main/res/drawable/gm_filled_emoji_food_beverage_vd_theme_24.xml new file mode 100644 index 000000000..989d0fabc --- /dev/null +++ b/emojipicker/src/main/res/drawable/gm_filled_emoji_food_beverage_vd_theme_24.xml @@ -0,0 +1,15 @@ + + + + + + diff --git a/emojipicker/src/main/res/drawable/gm_filled_emoji_nature_vd_theme_24.xml b/emojipicker/src/main/res/drawable/gm_filled_emoji_nature_vd_theme_24.xml new file mode 100644 index 000000000..c259fba2c --- /dev/null +++ b/emojipicker/src/main/res/drawable/gm_filled_emoji_nature_vd_theme_24.xml @@ -0,0 +1,15 @@ + + + + + + diff --git a/emojipicker/src/main/res/drawable/gm_filled_emoji_objects_vd_theme_24.xml b/emojipicker/src/main/res/drawable/gm_filled_emoji_objects_vd_theme_24.xml new file mode 100644 index 000000000..5e028ac9c --- /dev/null +++ b/emojipicker/src/main/res/drawable/gm_filled_emoji_objects_vd_theme_24.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/emojipicker/src/main/res/drawable/gm_filled_emoji_people_vd_theme_24.xml b/emojipicker/src/main/res/drawable/gm_filled_emoji_people_vd_theme_24.xml new file mode 100644 index 000000000..bd647fe4b --- /dev/null +++ b/emojipicker/src/main/res/drawable/gm_filled_emoji_people_vd_theme_24.xml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/emojipicker/src/main/res/drawable/gm_filled_emoji_symbols_vd_theme_24.xml b/emojipicker/src/main/res/drawable/gm_filled_emoji_symbols_vd_theme_24.xml new file mode 100644 index 000000000..571cb545d --- /dev/null +++ b/emojipicker/src/main/res/drawable/gm_filled_emoji_symbols_vd_theme_24.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/gm_filled_emoji_transportation_vd_theme_24.xml b/emojipicker/src/main/res/drawable/gm_filled_emoji_transportation_vd_theme_24.xml new file mode 100644 index 000000000..99a165e2a --- /dev/null +++ b/emojipicker/src/main/res/drawable/gm_filled_emoji_transportation_vd_theme_24.xml @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/gm_filled_flag_vd_theme_24.xml b/emojipicker/src/main/res/drawable/gm_filled_flag_vd_theme_24.xml new file mode 100644 index 000000000..f3573b8a2 --- /dev/null +++ b/emojipicker/src/main/res/drawable/gm_filled_flag_vd_theme_24.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/emojipicker/src/main/res/drawable/handshake_shadow_skintone.xml b/emojipicker/src/main/res/drawable/handshake_shadow_skintone.xml new file mode 100644 index 000000000..04259f359 --- /dev/null +++ b/emojipicker/src/main/res/drawable/handshake_shadow_skintone.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/emojipicker/src/main/res/drawable/handshake_skintone_shadow.xml b/emojipicker/src/main/res/drawable/handshake_skintone_shadow.xml new file mode 100644 index 000000000..dfe4f213c --- /dev/null +++ b/emojipicker/src/main/res/drawable/handshake_skintone_shadow.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/emojipicker/src/main/res/drawable/holding_men_shadow_skintone.xml b/emojipicker/src/main/res/drawable/holding_men_shadow_skintone.xml new file mode 100644 index 000000000..4b84e94a6 --- /dev/null +++ b/emojipicker/src/main/res/drawable/holding_men_shadow_skintone.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/holding_men_skintone_shadow.xml b/emojipicker/src/main/res/drawable/holding_men_skintone_shadow.xml new file mode 100644 index 000000000..e9def1c60 --- /dev/null +++ b/emojipicker/src/main/res/drawable/holding_men_skintone_shadow.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/holding_people_shadow_skintone.xml b/emojipicker/src/main/res/drawable/holding_people_shadow_skintone.xml new file mode 100644 index 000000000..ebbd0f4cf --- /dev/null +++ b/emojipicker/src/main/res/drawable/holding_people_shadow_skintone.xml @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/holding_people_skintone_shadow.xml b/emojipicker/src/main/res/drawable/holding_people_skintone_shadow.xml new file mode 100644 index 000000000..039b6207d --- /dev/null +++ b/emojipicker/src/main/res/drawable/holding_people_skintone_shadow.xml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/holding_woman_man_shadow_skintone.xml b/emojipicker/src/main/res/drawable/holding_woman_man_shadow_skintone.xml new file mode 100644 index 000000000..a921ec264 --- /dev/null +++ b/emojipicker/src/main/res/drawable/holding_woman_man_shadow_skintone.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/holding_woman_man_skintone_shadow.xml b/emojipicker/src/main/res/drawable/holding_woman_man_skintone_shadow.xml new file mode 100644 index 000000000..85c332764 --- /dev/null +++ b/emojipicker/src/main/res/drawable/holding_woman_man_skintone_shadow.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/holding_women_shadow_skintone.xml b/emojipicker/src/main/res/drawable/holding_women_shadow_skintone.xml new file mode 100644 index 000000000..0e918b995 --- /dev/null +++ b/emojipicker/src/main/res/drawable/holding_women_shadow_skintone.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/holding_women_skintone_shadow.xml b/emojipicker/src/main/res/drawable/holding_women_skintone_shadow.xml new file mode 100644 index 000000000..035cc21ea --- /dev/null +++ b/emojipicker/src/main/res/drawable/holding_women_skintone_shadow.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/icon_tint_selector.xml b/emojipicker/src/main/res/drawable/icon_tint_selector.xml new file mode 100644 index 000000000..50a07511c --- /dev/null +++ b/emojipicker/src/main/res/drawable/icon_tint_selector.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/emojipicker/src/main/res/drawable/kiss_men_shadow_skintone.xml b/emojipicker/src/main/res/drawable/kiss_men_shadow_skintone.xml new file mode 100644 index 000000000..e3df38d56 --- /dev/null +++ b/emojipicker/src/main/res/drawable/kiss_men_shadow_skintone.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/kiss_men_skintone_shadow.xml b/emojipicker/src/main/res/drawable/kiss_men_skintone_shadow.xml new file mode 100644 index 000000000..2abbd8842 --- /dev/null +++ b/emojipicker/src/main/res/drawable/kiss_men_skintone_shadow.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/kiss_people_shadow_skintone.xml b/emojipicker/src/main/res/drawable/kiss_people_shadow_skintone.xml new file mode 100644 index 000000000..ddaa48390 --- /dev/null +++ b/emojipicker/src/main/res/drawable/kiss_people_shadow_skintone.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/kiss_people_skintone_shadow.xml b/emojipicker/src/main/res/drawable/kiss_people_skintone_shadow.xml new file mode 100644 index 000000000..f81d8633d --- /dev/null +++ b/emojipicker/src/main/res/drawable/kiss_people_skintone_shadow.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/kiss_woman_man_shadow_skintone.xml b/emojipicker/src/main/res/drawable/kiss_woman_man_shadow_skintone.xml new file mode 100644 index 000000000..118312377 --- /dev/null +++ b/emojipicker/src/main/res/drawable/kiss_woman_man_shadow_skintone.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/kiss_woman_man_skintone_shadow.xml b/emojipicker/src/main/res/drawable/kiss_woman_man_skintone_shadow.xml new file mode 100644 index 000000000..5ded1f960 --- /dev/null +++ b/emojipicker/src/main/res/drawable/kiss_woman_man_skintone_shadow.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/kiss_women_shadow_skintone.xml b/emojipicker/src/main/res/drawable/kiss_women_shadow_skintone.xml new file mode 100644 index 000000000..555d28cd5 --- /dev/null +++ b/emojipicker/src/main/res/drawable/kiss_women_shadow_skintone.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/kiss_women_skintone_shadow.xml b/emojipicker/src/main/res/drawable/kiss_women_skintone_shadow.xml new file mode 100644 index 000000000..61d91624b --- /dev/null +++ b/emojipicker/src/main/res/drawable/kiss_women_skintone_shadow.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/popup_view_rounded_background.xml b/emojipicker/src/main/res/drawable/popup_view_rounded_background.xml new file mode 100644 index 000000000..7ed98b76c --- /dev/null +++ b/emojipicker/src/main/res/drawable/popup_view_rounded_background.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/emojipicker/src/main/res/drawable/quantum_gm_ic_access_time_filled_vd_theme_24.xml b/emojipicker/src/main/res/drawable/quantum_gm_ic_access_time_filled_vd_theme_24.xml new file mode 100644 index 000000000..57e65b17f --- /dev/null +++ b/emojipicker/src/main/res/drawable/quantum_gm_ic_access_time_filled_vd_theme_24.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/emojipicker/src/main/res/drawable/ripple_emoji_view.xml b/emojipicker/src/main/res/drawable/ripple_emoji_view.xml new file mode 100644 index 000000000..9748a72e9 --- /dev/null +++ b/emojipicker/src/main/res/drawable/ripple_emoji_view.xml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/emojipicker/src/main/res/drawable/ripple_image_view.xml b/emojipicker/src/main/res/drawable/ripple_image_view.xml new file mode 100644 index 000000000..4c0c3a46d --- /dev/null +++ b/emojipicker/src/main/res/drawable/ripple_image_view.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/drawable/swap_horiz_vd_theme_24.xml b/emojipicker/src/main/res/drawable/swap_horiz_vd_theme_24.xml new file mode 100644 index 000000000..e3684d49f --- /dev/null +++ b/emojipicker/src/main/res/drawable/swap_horiz_vd_theme_24.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/emojipicker/src/main/res/drawable/underline_rounded.xml b/emojipicker/src/main/res/drawable/underline_rounded.xml new file mode 100644 index 000000000..6621ad5ab --- /dev/null +++ b/emojipicker/src/main/res/drawable/underline_rounded.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/emojipicker/src/main/res/drawable/variant_availability_indicator.xml b/emojipicker/src/main/res/drawable/variant_availability_indicator.xml new file mode 100644 index 000000000..3df2ec1ef --- /dev/null +++ b/emojipicker/src/main/res/drawable/variant_availability_indicator.xml @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/emojipicker/src/main/res/layout/category_text_view.xml b/emojipicker/src/main/res/layout/category_text_view.xml new file mode 100644 index 000000000..f1f8ac43d --- /dev/null +++ b/emojipicker/src/main/res/layout/category_text_view.xml @@ -0,0 +1,21 @@ + + + + + + diff --git a/emojipicker/src/main/res/layout/emoji_picker.xml b/emojipicker/src/main/res/layout/emoji_picker.xml new file mode 100644 index 000000000..62739a188 --- /dev/null +++ b/emojipicker/src/main/res/layout/emoji_picker.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/emojipicker/src/main/res/layout/emoji_picker_popup_bidirectional.xml b/emojipicker/src/main/res/layout/emoji_picker_popup_bidirectional.xml new file mode 100644 index 000000000..be0c3df79 --- /dev/null +++ b/emojipicker/src/main/res/layout/emoji_picker_popup_bidirectional.xml @@ -0,0 +1,26 @@ + + + diff --git a/emojipicker/src/main/res/layout/emoji_picker_popup_emoji_view.xml b/emojipicker/src/main/res/layout/emoji_picker_popup_emoji_view.xml new file mode 100644 index 000000000..d50dd939b --- /dev/null +++ b/emojipicker/src/main/res/layout/emoji_picker_popup_emoji_view.xml @@ -0,0 +1,32 @@ + + + + + + diff --git a/emojipicker/src/main/res/layout/emoji_picker_popup_image_view.xml b/emojipicker/src/main/res/layout/emoji_picker_popup_image_view.xml new file mode 100644 index 000000000..da10bf120 --- /dev/null +++ b/emojipicker/src/main/res/layout/emoji_picker_popup_image_view.xml @@ -0,0 +1,27 @@ + + + + diff --git a/emojipicker/src/main/res/layout/empty_category_text_view.xml b/emojipicker/src/main/res/layout/empty_category_text_view.xml new file mode 100644 index 000000000..b85ec8fad --- /dev/null +++ b/emojipicker/src/main/res/layout/empty_category_text_view.xml @@ -0,0 +1,11 @@ + + + diff --git a/emojipicker/src/main/res/layout/header_icon_holder.xml b/emojipicker/src/main/res/layout/header_icon_holder.xml new file mode 100644 index 000000000..d878bafa6 --- /dev/null +++ b/emojipicker/src/main/res/layout/header_icon_holder.xml @@ -0,0 +1,24 @@ + + + + + + + diff --git a/emojipicker/src/main/res/layout/variant_popup.xml b/emojipicker/src/main/res/layout/variant_popup.xml new file mode 100644 index 000000000..791a98ba1 --- /dev/null +++ b/emojipicker/src/main/res/layout/variant_popup.xml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/emojipicker/src/main/res/raw/emoji_category_activity.csv b/emojipicker/src/main/res/raw/emoji_category_activity.csv new file mode 100644 index 000000000..cb7c32877 --- /dev/null +++ b/emojipicker/src/main/res/raw/emoji_category_activity.csv @@ -0,0 +1,85 @@ +🎃,jack-o-lantern +🎄,Christmas tree +🎆,fireworks +🎇,sparkler +🧨,firecracker +✨,sparkles +🎈,balloon +🎉,party popper +🎊,confetti ball +🎋,tanabata tree +🎍,pine decoration +🎎,Japanese dolls +🎏,carp streamer +🎐,wind chime +🎑,moon viewing ceremony +🧧,red envelope +🎀,ribbon +🎁,wrapped gift +🎗️,reminder ribbon +🎟️,admission tickets +🎫,ticket +🎖️,military medal +🏆,trophy +🏅,sports medal +🥇,1st place medal +🥈,2nd place medal +🥉,3rd place medal +⚽,soccer ball +⚾,baseball +🥎,softball +🏀,basketball +🏐,volleyball +🏈,american football +🏉,rugby football +🎾,tennis +🥏,flying disc +🎳,bowling +🏏,cricket game +🏑,field hockey +🏒,ice hockey +🥍,lacrosse +🏓,ping pong +🏸,badminton +🥊,boxing glove +🥋,martial arts uniform +🥅,goal net +⛳,flag in hole +⛸️,ice skate +🎣,fishing pole +🤿,diving mask +🎽,running shirt +🎿,skis +🛷,sled +🥌,curling stone +🎯,bullseye +🪀,yo-yo +🪁,kite +🔫,water pistol +🎱,pool 8 ball +🔮,crystal ball +🪄,magic wand +🎮,video game +🕹️,joystick +🎰,slot machine +🎲,game die +🧩,puzzle piece +🧸,teddy bear +🪅,piñata +🪩,mirror ball +🪆,nesting dolls +♠️,spade suit +♥️,heart suit +♦️,diamond suit +♣️,club suit +♟️,chess pawn +🃏,joker +🀄,mahjong red dragon +🎴,flower playing cards +🎭,performing arts +🖼️,framed picture +🎨,artist palette +🧵,thread +🪡,sewing needle +🧶,yarn +🪢,knot diff --git a/emojipicker/src/main/res/raw/emoji_category_animals_nature.csv b/emojipicker/src/main/res/raw/emoji_category_animals_nature.csv new file mode 100644 index 000000000..d35c3e803 --- /dev/null +++ b/emojipicker/src/main/res/raw/emoji_category_animals_nature.csv @@ -0,0 +1,152 @@ +🐵,monkey face +🐒,monkey +🦍,gorilla +🦧,orangutan +🐶,dog face +🐕,dog +🦮,guide dog +🐕‍🦺,service dog +🐩,poodle +🐺,wolf +🦊,fox +🦝,raccoon +🐱,cat face +🐈,cat +🐈‍⬛,black cat +🦁,lion +🐯,tiger face +🐅,tiger +🐆,leopard +🐴,horse face +🫎,moose +🫏,donkey +🐎,horse +🦄,unicorn +🦓,zebra +🦌,deer +🦬,bison +🐮,cow face +🐂,ox +🐃,water buffalo +🐄,cow +🐷,pig face +🐖,pig +🐗,boar +🐽,pig nose +🐏,ram +🐑,ewe +🐐,goat +🐪,camel +🐫,two-hump camel +🦙,llama +🦒,giraffe +🐘,elephant +🦣,mammoth +🦏,rhinoceros +🦛,hippopotamus +🐭,mouse face +🐁,mouse +🐀,rat +🐹,hamster +🐰,rabbit face +🐇,rabbit +🐿️,chipmunk +🦫,beaver +🦔,hedgehog +🦇,bat +🐻,bear +🐻‍❄️,polar bear +🐨,koala +🐼,panda +🦥,sloth +🦦,otter +🦨,skunk +🦘,kangaroo +🦡,badger +🐾,paw prints +🦃,turkey +🐔,chicken +🐓,rooster +🐣,hatching chick +🐤,baby chick +🐥,front-facing baby chick +🐦,bird +🐧,penguin +🕊️,dove +🦅,eagle +🦆,duck +🦢,swan +🦉,owl +🦤,dodo +🪶,feather +🦩,flamingo +🦚,peacock +🦜,parrot +🪽,wing +🐦‍⬛,black bird +🪿,goose +🐸,frog +🐊,crocodile +🐢,turtle +🦎,lizard +🐍,snake +🐲,dragon face +🐉,dragon +🦕,sauropod +🦖,T-Rex +🐳,spouting whale +🐋,whale +🐬,dolphin +🦭,seal +🐟,fish +🐠,tropical fish +🐡,blowfish +🦈,shark +🐙,octopus +🐚,spiral shell +🪸,coral +🪼,jellyfish +🐌,snail +🦋,butterfly +🐛,bug +🐜,ant +🐝,honeybee +🪲,beetle +🐞,lady beetle +🦗,cricket +🪳,cockroach +🕷️,spider +🕸️,spider web +🦂,scorpion +🦟,mosquito +🪰,fly +🪱,worm +🦠,microbe +💐,bouquet +🌸,cherry blossom +💮,white flower +🪷,lotus +🏵️,rosette +🌹,rose +🥀,wilted flower +🌺,hibiscus +🌻,sunflower +🌼,blossom +🌷,tulip +🪻,hyacinth +🌱,seedling +🪴,potted plant +🌲,evergreen tree +🌳,deciduous tree +🌴,palm tree +🌵,cactus +🌾,sheaf of rice +🌿,herb +☘️,shamrock +🍀,four leaf clover +🍁,maple leaf +🍂,fallen leaf +🍃,leaf fluttering in wind +🪹,empty nest +🪺,nest with eggs +🍄,mushroom diff --git a/emojipicker/src/main/res/raw/emoji_category_emotions.csv b/emojipicker/src/main/res/raw/emoji_category_emotions.csv new file mode 100644 index 000000000..138a2816a --- /dev/null +++ b/emojipicker/src/main/res/raw/emoji_category_emotions.csv @@ -0,0 +1,166 @@ +😀,grinning face +😃,grinning face with big eyes +😄,grinning face with smiling eyes +😁,beaming face with smiling eyes +😆,grinning squinting face +😅,grinning face with sweat +🤣,rolling on the floor laughing +😂,face with tears of joy +🙂,slightly smiling face +🙃,upside-down face +🫠,melting face +😉,winking face +😊,smiling face with smiling eyes +😇,smiling face with halo +🥰,smiling face with hearts +😍,smiling face with heart-eyes +🤩,star-struck +😘,face blowing a kiss +😗,kissing face +☺️,smiling face +😚,kissing face with closed eyes +😙,kissing face with smiling eyes +🥲,smiling face with tear +😋,face savoring food +😛,face with tongue +😜,winking face with tongue +🤪,zany face +😝,squinting face with tongue +🤑,money-mouth face +🤗,smiling face with open hands +🤭,face with hand over mouth +🫢,face with open eyes and hand over mouth +🫣,face with peeking eye +🤫,shushing face +🤔,thinking face +🫡,saluting face +🤐,zipper-mouth face +🤨,face with raised eyebrow +😐,neutral face +😑,expressionless face +😶,face without mouth +🫥,dotted line face +😶‍🌫️,face in clouds +😏,smirking face +😒,unamused face +🙄,face with rolling eyes +😬,grimacing face +😮‍💨,face exhaling +🤥,lying face +🫨,shaking face +😌,relieved face +😔,pensive face +😪,sleepy face +🤤,drooling face +😴,sleeping face +😷,face with medical mask +🤒,face with thermometer +🤕,face with head-bandage +🤢,nauseated face +🤮,face vomiting +🤧,sneezing face +🥵,hot face +🥶,cold face +🥴,woozy face +😵,face with crossed-out eyes +😵‍💫,face with spiral eyes +🤯,exploding head +🤠,cowboy hat face +🥳,partying face +🥸,disguised face +😎,smiling face with sunglasses +🤓,nerd face +🧐,face with monocle +😕,confused face +🫤,face with diagonal mouth +😟,worried face +🙁,slightly frowning face +☹️,frowning face +😮,face with open mouth +😯,hushed face +😲,astonished face +😳,flushed face +🥺,pleading face +🥹,face holding back tears +😦,frowning face with open mouth +😧,anguished face +😨,fearful face +😰,anxious face with sweat +😥,sad but relieved face +😢,crying face +😭,loudly crying face +😱,face screaming in fear +😖,confounded face +😣,persevering face +😞,disappointed face +😓,downcast face with sweat +😩,weary face +😫,tired face +🥱,yawning face +😤,face with steam from nose +😡,enraged face +😠,angry face +🤬,face with symbols on mouth +😈,smiling face with horns +👿,angry face with horns +💀,skull dead +☠️,skull and crossbones +💩,pile of poo +🤡,clown face +👹,ogre +👺,goblin +👻,ghost +👽,alien +👾,alien monster +🤖,robot +😺,grinning cat +😸,grinning cat with smiling eyes +😹,cat with tears of joy +😻,smiling cat with heart-eyes +😼,cat with wry smile +😽,kissing cat kiss +🙀,weary cat +😿,crying cat +😾,pouting cat +🙈,see-no-evil monkey +🙉,hear-no-evil monkey +🙊,speak-no-evil monkey +💌,love letter +💘,heart with arrow +💝,heart with ribbon +💖,sparkling heart +💗,growing heart +💓,beating heart +💞,revolving hearts +💕,two hearts +💟,heart decoration +❣️,heart exclamation +💔,broken heart +❤️‍🔥,heart on fire +❤️‍🩹,mending heart +❤️,red heart +🩷,pink heart +🧡,orange heart +💛,yellow heart +💚,green heart +💙,blue heart +🩵,light blue heart +💜,purple heart +🤎,brown heart +🖤,black heart +🩶,grey heart +🤍,white heart +💋,kiss mark +💯,hundred points +💢,anger symbol +💥,collision +💫,dizzy +💦,sweat droplets +💨,dashing away +🕳️,hole +💬,speech balloon +👁️‍🗨️,eye in speech bubble +🗨️,left speech bubble +🗯️,right anger bubble +💭,thought balloon +💤,ZZZ sleeping diff --git a/emojipicker/src/main/res/raw/emoji_category_flags.csv b/emojipicker/src/main/res/raw/emoji_category_flags.csv new file mode 100644 index 000000000..96e02f6be --- /dev/null +++ b/emojipicker/src/main/res/raw/emoji_category_flags.csv @@ -0,0 +1,269 @@ +🏁,chequered flag +🚩,triangular flag +🎌,crossed flags +🏴,black flag +🏳️,white flag +🏳️‍🌈,rainbow flag gay +🏳️‍⚧️,transgender flag +🏴‍☠️,pirate flag +🇦🇨,flag: Ascension Island +🇦🇩,flag: Andorra +🇦🇪,flag: United Arab Emirates +🇦🇫,flag: Afghanistan +🇦🇬,flag: Antigua & Barbuda +🇦🇮,flag: Anguilla +🇦🇱,flag: Albania +🇦🇲,flag: Armenia +🇦🇴,flag: Angola +🇦🇶,flag: Antarctica +🇦🇷,flag: Argentina +🇦🇸,flag: American Samoa +🇦🇹,flag: Austria +🇦🇺,flag: Australia +🇦🇼,flag: Aruba +🇦🇽,flag: Åland Islands +🇦🇿,flag: Azerbaijan +🇧🇦,flag: Bosnia & Herzegovina +🇧🇧,flag: Barbados +🇧🇩,flag: Bangladesh +🇧🇪,flag: Belgium +🇧🇫,flag: Burkina Faso +🇧🇬,flag: Bulgaria +🇧🇭,flag: Bahrain +🇧🇮,flag: Burundi +🇧🇯,flag: Benin +🇧🇱,flag: St. Barthélemy +🇧🇲,flag: Bermuda +🇧🇳,flag: Brunei +🇧🇴,flag: Bolivia +🇧🇶,flag: Caribbean Netherlands +🇧🇷,flag: Brazil +🇧🇸,flag: Bahamas +🇧🇹,flag: Bhutan +🇧🇻,flag: Bouvet Island +🇧🇼,flag: Botswana +🇧🇾,flag: Belarus +🇧🇿,flag: Belize +🇨🇦,flag: Canada +🇨🇨,flag: Cocos (Keeling) Islands +🇨🇩,flag: Congo - Kinshasa +🇨🇫,flag: Central African Republic +🇨🇬,flag: Congo - Brazzaville +🇨🇭,flag: Switzerland +🇨🇮,flag: Côte d’Ivoire +🇨🇰,flag: Cook Islands +🇨🇱,flag: Chile +🇨🇲,flag: Cameroon +🇨🇳,flag: China +🇨🇴,flag: Colombia +🇨🇵,flag: Clipperton Island +🇨🇷,flag: Costa Rica +🇨🇺,flag: Cuba +🇨🇻,flag: Cape Verde +🇨🇼,flag: Curaçao +🇨🇽,flag: Christmas Island +🇨🇾,flag: Cyprus +🇨🇿,flag: Czechia +🇩🇪,flag: Germany +🇩🇬,flag: Diego Garcia +🇩🇯,flag: Djibouti +🇩🇰,flag: Denmark +🇩🇲,flag: Dominica +🇩🇴,flag: Dominican Republic +🇩🇿,flag: Algeria +🇪🇦,flag: Ceuta & Melilla +🇪🇨,flag: Ecuador +🇪🇪,flag: Estonia +🇪🇬,flag: Egypt +🇪🇭,flag: Western Sahara +🇪🇷,flag: Eritrea +🇪🇸,flag: Spain +🇪🇹,flag: Ethiopia +🇪🇺,flag: European Union +🇫🇮,flag: Finland +🇫🇯,flag: Fiji +🇫🇰,flag: Falkland Islands +🇫🇲,flag: Micronesia +🇫🇴,flag: Faroe Islands +🇫🇷,flag: France +🇬🇦,flag: Gabon +🇬🇧,flag: United Kingdom +🇬🇩,flag: Grenada +🇬🇪,flag: Georgia +🇬🇫,flag: French Guiana +🇬🇬,flag: Guernsey +🇬🇭,flag: Ghana +🇬🇮,flag: Gibraltar +🇬🇱,flag: Greenland +🇬🇲,flag: Gambia +🇬🇳,flag: Guinea +🇬🇵,flag: Guadeloupe +🇬🇶,flag: Equatorial Guinea +🇬🇷,flag: Greece +🇬🇸,flag: South Georgia & South Sandwich Islands +🇬🇹,flag: Guatemala +🇬🇺,flag: Guam +🇬🇼,flag: Guinea-Bissau +🇬🇾,flag: Guyana +🇭🇰,flag: Hong Kong SAR China +🇭🇲,flag: Heard & McDonald Islands +🇭🇳,flag: Honduras +🇭🇷,flag: Croatia +🇭🇹,flag: Haiti +🇭🇺,flag: Hungary +🇮🇨,flag: Canary Islands +🇮🇩,flag: Indonesia +🇮🇪,flag: Ireland +🇮🇱,flag: Israel +🇮🇲,flag: Isle of Man +🇮🇳,flag: India +🇮🇴,flag: British Indian Ocean Territory +🇮🇶,flag: Iraq +🇮🇷,flag: Iran +🇮🇸,flag: Iceland +🇮🇹,flag: Italy +🇯🇪,flag: Jersey +🇯🇲,flag: Jamaica +🇯🇴,flag: Jordan +🇯🇵,flag: Japan +🇰🇪,flag: Kenya +🇰🇬,flag: Kyrgyzstan +🇰🇭,flag: Cambodia +🇰🇮,flag: Kiribati +🇰🇲,flag: Comoros +🇰🇳,flag: St. Kitts & Nevis +🇰🇵,flag: North Korea +🇰🇷,flag: South Korea +🇰🇼,flag: Kuwait +🇰🇾,flag: Cayman Islands +🇰🇿,flag: Kazakhstan +🇱🇦,flag: Laos +🇱🇧,flag: Lebanon +🇱🇨,flag: St. Lucia +🇱🇮,flag: Liechtenstein +🇱🇰,flag: Sri Lanka +🇱🇷,flag: Liberia +🇱🇸,flag: Lesotho +🇱🇹,flag: Lithuania +🇱🇺,flag: Luxembourg +🇱🇻,flag: Latvia +🇱🇾,flag: Libya +🇲🇦,flag: Morocco +🇲🇨,flag: Monaco +🇲🇩,flag: Moldova +🇲🇪,flag: Montenegro +🇲🇫,flag: St. Martin +🇲🇬,flag: Madagascar +🇲🇭,flag: Marshall Islands +🇲🇰,flag: North Macedonia +🇲🇱,flag: Mali +🇲🇲,flag: Myanmar (Burma) +🇲🇳,flag: Mongolia +🇲🇴,flag: Macao SAR China +🇲🇵,flag: Northern Mariana Islands +🇲🇶,flag: Martinique +🇲🇷,flag: Mauritania +🇲🇸,flag: Montserrat +🇲🇹,flag: Malta +🇲🇺,flag: Mauritius +🇲🇻,flag: Maldives +🇲🇼,flag: Malawi +🇲🇽,flag: Mexico +🇲🇾,flag: Malaysia +🇲🇿,flag: Mozambique +🇳🇦,flag: Namibia +🇳🇨,flag: New Caledonia +🇳🇪,flag: Niger +🇳🇫,flag: Norfolk Island +🇳🇬,flag: Nigeria +🇳🇮,flag: Nicaragua +🇳🇱,flag: Netherlands +🇳🇴,flag: Norway +🇳🇵,flag: Nepal +🇳🇷,flag: Nauru +🇳🇺,flag: Niue +🇳🇿,flag: New Zealand +🇴🇲,flag: Oman +🇵🇦,flag: Panama +🇵🇪,flag: Peru +🇵🇫,flag: French Polynesia +🇵🇬,flag: Papua New Guinea +🇵🇭,flag: Philippines +🇵🇰,flag: Pakistan +🇵🇱,flag: Poland +🇵🇲,flag: St. Pierre & Miquelon +🇵🇳,flag: Pitcairn Islands +🇵🇷,flag: Puerto Rico +🇵🇸,flag: Palestinian Territories +🇵🇹,flag: Portugal +🇵🇼,flag: Palau +🇵🇾,flag: Paraguay +🇶🇦,flag: Qatar +🇷🇪,flag: Réunion +🇷🇴,flag: Romania +🇷🇸,flag: Serbia +🇷🇺,flag: Russia +🇷🇼,flag: Rwanda +🇸🇦,flag: Saudi Arabia +🇸🇧,flag: Solomon Islands +🇸🇨,flag: Seychelles +🇸🇩,flag: Sudan +🇸🇪,flag: Sweden +🇸🇬,flag: Singapore +🇸🇭,flag: St. Helena +🇸🇮,flag: Slovenia +🇸🇯,flag: Svalbard & Jan Mayen +🇸🇰,flag: Slovakia +🇸🇱,flag: Sierra Leone +🇸🇲,flag: San Marino +🇸🇳,flag: Senegal +🇸🇴,flag: Somalia +🇸🇷,flag: Suriname +🇸🇸,flag: South Sudan +🇸🇹,flag: São Tomé & Príncipe +🇸🇻,flag: El Salvador +🇸🇽,flag: Sint Maarten +🇸🇾,flag: Syria +🇸🇿,flag: Eswatini +🇹🇦,flag: Tristan da Cunha +🇹🇨,flag: Turks & Caicos Islands +🇹🇩,flag: Chad +🇹🇫,flag: French Southern Territories +🇹🇬,flag: Togo +🇹🇭,flag: Thailand +🇹🇯,flag: Tajikistan +🇹🇰,flag: Tokelau +🇹🇱,flag: Timor-Leste +🇹🇲,flag: Turkmenistan +🇹🇳,flag: Tunisia +🇹🇴,flag: Tonga +🇹🇷,flag: Turkey +🇹🇹,flag: Trinidad & Tobago +🇹🇻,flag: Tuvalu +🇹🇼,flag: Taiwan +🇹🇿,flag: Tanzania +🇺🇦,flag: Ukraine +🇺🇬,flag: Uganda +🇺🇲,flag: U.S. Outlying Islands +🇺🇳,flag: United Nations +🇺🇸,flag: United States +🇺🇾,flag: Uruguay +🇺🇿,flag: Uzbekistan +🇻🇦,flag: Vatican City +🇻🇨,flag: St. Vincent & Grenadines +🇻🇪,flag: Venezuela +🇻🇬,flag: British Virgin Islands +🇻🇮,flag: U.S. Virgin Islands +🇻🇳,flag: Vietnam +🇻🇺,flag: Vanuatu +🇼🇫,flag: Wallis & Futuna +🇼🇸,flag: Samoa +🇽🇰,flag: Kosovo +🇾🇪,flag: Yemen +🇾🇹,flag: Mayotte +🇿🇦,flag: South Africa +🇿🇲,flag: Zambia +🇿🇼,flag: Zimbabwe +🏴󠁧󠁢󠁥󠁮󠁧󠁿,flag: England +🏴󠁧󠁢󠁳󠁣󠁴󠁿,flag: Scotland +🏴󠁧󠁢󠁷󠁬󠁳󠁿,flag: Wales diff --git a/emojipicker/src/main/res/raw/emoji_category_food_drink.csv b/emojipicker/src/main/res/raw/emoji_category_food_drink.csv new file mode 100644 index 000000000..e20c5d43e --- /dev/null +++ b/emojipicker/src/main/res/raw/emoji_category_food_drink.csv @@ -0,0 +1,133 @@ +🍇,grapes +🍈,melon +🍉,watermelon +🍊,tangerine +🍋,lemon +🍌,banana +🍍,pineapple +🥭,mango +🍎,red apple +🍏,green apple +🍐,pear +🍑,peach +🍒,cherries +🍓,strawberry +🫐,blueberries +🥝,kiwi fruit +🍅,tomato +🫒,olive +🥥,coconut +🥑,avocado +🍆,eggplant +🥔,potato +🥕,carrot +🌽,ear of corn +🌶️,hot pepper +🫑,bell pepper +🥒,cucumber +🥬,leafy green +🥦,broccoli +🧄,garlic +🧅,onion +🥜,peanuts +🫘,beans +🌰,chestnut +🫚,ginger root +🫛,pea pod +🍞,bread +🥐,croissant +🥖,baguette bread +🫓,flatbread +🥨,pretzel +🥯,bagel +🥞,pancakes +🧇,waffle +🧀,cheese wedge +🍖,meat on bone +🍗,poultry leg +🥩,cut of meat +🥓,bacon +🍔,hamburger +🍟,french fries +🍕,pizza +🌭,hot dog +🥪,sandwich +🌮,taco +🌯,burrito +🫔,tamale +🥙,stuffed flatbread +🧆,falafel +🥚,egg +🍳,cooking +🥘,shallow pan of food +🍲,pot of food +🫕,fondue +🥣,bowl with spoon +🥗,green salad +🍿,popcorn +🧈,butter +🧂,salt +🥫,canned food +🍱,bento box +🍘,rice cracker +🍙,rice ball +🍚,cooked rice +🍛,curry rice +🍜,steaming bowl +🍝,spaghetti +🍠,roasted sweet potato +🍢,oden +🍣,sushi +🍤,fried shrimp +🍥,fish cake with swirl +🥮,moon cake +🍡,dango +🥟,dumpling +🥠,fortune cookie +🥡,takeout box +🦀,crab +🦞,lobster +🦐,shrimp +🦑,squid +🦪,oyster +🍦,soft ice cream +🍧,shaved ice +🍨,ice cream +🍩,doughnut +🍪,cookie +🎂,birthday cake +🍰,shortcake +🧁,cupcake +🥧,pie +🍫,chocolate bar +🍬,candy +🍭,lollipop +🍮,custard +🍯,honey pot +🍼,baby bottle +🥛,glass of milk +☕,hot beverage +🫖,teapot +🍵,teacup without handle +🍶,sake +🍾,bottle with popping cork +🍷,wine glass +🍸,cocktail glass +🍹,tropical drink +🍺,beer mug +🍻,clinking beer mugs +🥂,clinking glasses +🥃,tumbler glass +🫗,pouring liquid +🥤,cup with straw +🧋,bubble tea +🧃,beverage box +🧉,mate +🧊,ice +🥢,chopsticks +🍽️,fork and knife with plate +🍴,fork and knife +🥄,spoon +🔪,kitchen knife +🫙,jar +🏺,amphora diff --git a/emojipicker/src/main/res/raw/emoji_category_objects.csv b/emojipicker/src/main/res/raw/emoji_category_objects.csv new file mode 100644 index 000000000..15834446d --- /dev/null +++ b/emojipicker/src/main/res/raw/emoji_category_objects.csv @@ -0,0 +1,261 @@ +👓,glasses +🕶️,sunglasses +🥽,goggles +🥼,lab coat +🦺,safety vest +👔,necktie +👕,t-shirt +👖,jeans +🧣,scarf +🧤,gloves +🧥,coat +🧦,socks +👗,dress +👘,kimono +🥻,sari +🩱,one-piece swimsuit +🩲,briefs +🩳,shorts +👙,bikini +👚,woman’s clothes +🪭,folding hand fan +👛,purse +👜,handbag +👝,clutch bag +🛍️,shopping bags +🎒,backpack +🩴,thong sandal +👞,man’s shoe +👟,running shoe +🥾,hiking boot +🥿,flat shoe +👠,high-heeled shoe +👡,woman’s sandal +🩰,ballet shoes +👢,woman’s boot +🪮,hair pick +👑,crown +👒,woman’s hat +🎩,top hat +🎓,graduation cap +🧢,billed cap +🪖,military helmet +⛑️,rescue worker’s helmet +📿,prayer beads +💄,lipstick +💍,ring +💎,gem stone +🔇,muted speaker +🔈,speaker low volume +🔉,speaker medium volume +🔊,speaker high volume +📢,loudspeaker +📣,megaphone +📯,postal horn +🔔,bell +🔕,bell with slash +🎼,musical score +🎵,musical note +🎶,musical notes +🎙️,studio microphone +🎚️,level slider +🎛️,control knobs +🎤,microphone +🎧,headphone +📻,radio +🎷,saxophone +🪗,accordion +🎸,guitar +🎹,musical keyboard +🎺,trumpet +🎻,violin +🪕,banjo +🥁,drum +🪘,long drum +🪇,maracas +🪈,flute +📱,mobile phone +📲,mobile phone with arrow +☎️,telephone +📞,telephone receiver +📟,pager +📠,fax machine +🔋,battery +🪫,low battery +🔌,electric plug +💻,laptop +🖥️,desktop computer +🖨️,printer +⌨️,keyboard +🖱️,computer mouse +🖲️,trackball +💽,computer disk +💾,floppy disk +💿,optical disk +📀,dvd +🧮,abacus +🎥,movie camera +🎞️,film frames +📽️,film projector +🎬,clapper board +📺,television +📷,camera +📸,camera with flash +📹,video camera +📼,videocassette +🔍,magnifying glass tilted left +🔎,magnifying glass tilted right +🕯️,candle +💡,light bulb +🔦,flashlight +🏮,red paper lantern +🪔,diya lamp +📔,notebook with decorative cover +📕,closed book +📖,open book +📗,green book +📘,blue book +📙,orange book +📚,books +📓,notebook +📒,ledger +📃,page with curl +📜,scroll +📄,page facing up +📰,newspaper +🗞️,rolled-up newspaper +📑,bookmark tabs +🔖,bookmark +🏷️,label +💰,money bag +🪙,coin +💴,yen banknote +💵,dollar banknote +💶,euro banknote +💷,pound banknote +💸,money with wings +💳,credit card +🧾,receipt +💹,chart increasing with yen +✉️,envelope +📧,e-mail +📨,incoming envelope +📩,envelope with arrow +📤,outbox tray +📥,inbox tray +📦,package +📫,closed mailbox with raised flag +📪,closed mailbox with lowered flag +📬,open mailbox with raised flag +📭,open mailbox with lowered flag +📮,postbox +🗳️,ballot box with ballot +✏️,pencil +✒️,black nib +🖋️,fountain pen +🖊️,pen +🖌️,paintbrush +🖍️,crayon +📝,memo +💼,briefcase +📁,file folder +📂,open file folder +🗂️,card index dividers +📅,calendar +📆,tear-off calendar +🗒️,spiral notepad +🗓️,spiral calendar +📇,card index +📈,chart increasing +📉,chart decreasing +📊,bar chart +📋,clipboard +📌,pushpin +📍,round pushpin +📎,paperclip +🖇️,linked paperclips +📏,straight ruler +📐,triangular ruler +✂️,scissors +🗃️,card file box +🗄️,file cabinet +🗑️,wastebasket +🔒,locked +🔓,unlocked +🔏,locked with pen +🔐,locked with key +🔑,key +🗝️,old key +🔨,hammer +🪓,axe +⛏️,pick +⚒️,hammer and pick +🛠️,hammer and wrench +🗡️,dagger +⚔️,crossed swords +💣,bomb +🪃,boomerang +🏹,bow and arrow +🛡️,shield +🪚,carpentry saw +🔧,wrench +🪛,screwdriver +🔩,nut and bolt +⚙️,gear +🗜️,clamp +⚖️,balance scale +🦯,white cane +🔗,link +⛓️,chains +🪝,hook +🧰,toolbox +🧲,magnet +🪜,ladder +⚗️,alembic +🧪,test tube +🧫,petri dish +🧬,dna +🔬,microscope +🔭,telescope +📡,satellite antenna +💉,syringe +🩸,drop of blood +💊,pill +🩹,adhesive bandage +🩼,crutch +🩺,stethoscope +🩻,x-ray +🚪,door +🛗,elevator +🪞,mirror +🪟,window +🛏️,bed +🛋️,couch and lamp +🪑,chair +🚽,toilet +🪠,plunger +🚿,shower +🛁,bathtub +🪤,mouse trap +🪒,razor +🧴,lotion bottle +🧷,safety pin +🧹,broom +🧺,basket +🧻,roll of paper +🪣,bucket +🧼,soap +🫧,bubbles +🪥,toothbrush +🧽,sponge +🧯,fire extinguisher +🛒,shopping cart +🚬,cigarette depressed +⚰️,coffin +🪦,headstone +⚱️,funeral urn +🧿,nazar amulet +🪬,hamsa +🗿,moai +🪧,placard +🪪,identification card diff --git a/emojipicker/src/main/res/raw/emoji_category_people.csv b/emojipicker/src/main/res/raw/emoji_category_people.csv new file mode 100644 index 000000000..dcaabc764 --- /dev/null +++ b/emojipicker/src/main/res/raw/emoji_category_people.csv @@ -0,0 +1,314 @@ +👋,waving hand hello slap,👋🏻,👋🏻,👋🏼,👋🏻,👋🏼,👋🏽,👋🏻,👋🏼,👋🏽,👋🏾,👋🏻,👋🏼,👋🏽,👋🏾,👋🏿 +🤚,raised back of hand,🤚🏻,🤚🏻,🤚🏼,🤚🏻,🤚🏼,🤚🏽,🤚🏻,🤚🏼,🤚🏽,🤚🏾,🤚🏻,🤚🏼,🤚🏽,🤚🏾,🤚🏿 +🖐️,hand with fingers splayed,🖐🏻,🖐🏻,🖐🏼,🖐🏻,🖐🏼,🖐🏽,🖐🏻,🖐🏼,🖐🏽,🖐🏾,🖐🏻,🖐🏼,🖐🏽,🖐🏾,🖐🏿 +✋,raised hand,✋🏻,✋🏻,✋🏼,✋🏻,✋🏼,✋🏽,✋🏻,✋🏼,✋🏽,✋🏾,✋🏻,✋🏼,✋🏽,✋🏾,✋🏿 +🖖,vulcan salute,🖖🏻,🖖🏻,🖖🏼,🖖🏻,🖖🏼,🖖🏽,🖖🏻,🖖🏼,🖖🏽,🖖🏾,🖖🏻,🖖🏼,🖖🏽,🖖🏾,🖖🏿 +🫱,rightwards hand,🫱🏻,🫱🏻,🫱🏼,🫱🏻,🫱🏼,🫱🏽,🫱🏻,🫱🏼,🫱🏽,🫱🏾,🫱🏻,🫱🏼,🫱🏽,🫱🏾,🫱🏿 +🫲,leftwards hand,🫲🏻,🫲🏻,🫲🏼,🫲🏻,🫲🏼,🫲🏽,🫲🏻,🫲🏼,🫲🏽,🫲🏾,🫲🏻,🫲🏼,🫲🏽,🫲🏾,🫲🏿 +🫳,palm down hand,🫳🏻,🫳🏻,🫳🏼,🫳🏻,🫳🏼,🫳🏽,🫳🏻,🫳🏼,🫳🏽,🫳🏾,🫳🏻,🫳🏼,🫳🏽,🫳🏾,🫳🏿 +🫴,palm up hand,🫴🏻,🫴🏻,🫴🏼,🫴🏻,🫴🏼,🫴🏽,🫴🏻,🫴🏼,🫴🏽,🫴🏾,🫴🏻,🫴🏼,🫴🏽,🫴🏾,🫴🏿 +🫷,leftwards pushing hand,🫷🏻,🫷🏻,🫷🏼,🫷🏻,🫷🏼,🫷🏽,🫷🏻,🫷🏼,🫷🏽,🫷🏾,🫷🏻,🫷🏼,🫷🏽,🫷🏾,🫷🏿 +🫸,rightwards pushing hand,🫸🏻,🫸🏻,🫸🏼,🫸🏻,🫸🏼,🫸🏽,🫸🏻,🫸🏼,🫸🏽,🫸🏾,🫸🏻,🫸🏼,🫸🏽,🫸🏾,🫸🏿 +👌,OK hand best,👌🏻,👌🏻,👌🏼,👌🏻,👌🏼,👌🏽,👌🏻,👌🏼,👌🏽,👌🏾,👌🏻,👌🏼,👌🏽,👌🏾,👌🏿 +🤌,pinched fingers quality,🤌🏻,🤌🏻,🤌🏼,🤌🏻,🤌🏼,🤌🏽,🤌🏻,🤌🏼,🤌🏽,🤌🏾,🤌🏻,🤌🏼,🤌🏽,🤌🏾,🤌🏿 +🤏,pinching hand,🤏🏻,🤏🏻,🤏🏼,🤏🏻,🤏🏼,🤏🏽,🤏🏻,🤏🏼,🤏🏽,🤏🏾,🤏🏻,🤏🏼,🤏🏽,🤏🏾,🤏🏿 +✌️,victory hand,✌🏻,✌🏻,✌🏼,✌🏻,✌🏼,✌🏽,✌🏻,✌🏼,✌🏽,✌🏾,✌🏻,✌🏼,✌🏽,✌🏾,✌🏿 +🤞,crossed fingers,🤞🏻,🤞🏻,🤞🏼,🤞🏻,🤞🏼,🤞🏽,🤞🏻,🤞🏼,🤞🏽,🤞🏾,🤞🏻,🤞🏼,🤞🏽,🤞🏾,🤞🏿 +🫰,hand with index finger and thumb crossed,🫰🏻,🫰🏻,🫰🏼,🫰🏻,🫰🏼,🫰🏽,🫰🏻,🫰🏼,🫰🏽,🫰🏾,🫰🏻,🫰🏼,🫰🏽,🫰🏾,🫰🏿 +🤟,love-you gesture,🤟🏻,🤟🏻,🤟🏼,🤟🏻,🤟🏼,🤟🏽,🤟🏻,🤟🏼,🤟🏽,🤟🏾,🤟🏻,🤟🏼,🤟🏽,🤟🏾,🤟🏿 +🤘,sign of the horns,🤘🏻,🤘🏻,🤘🏼,🤘🏻,🤘🏼,🤘🏽,🤘🏻,🤘🏼,🤘🏽,🤘🏾,🤘🏻,🤘🏼,🤘🏽,🤘🏾,🤘🏿 +🤙,call me hand,🤙🏻,🤙🏻,🤙🏼,🤙🏻,🤙🏼,🤙🏽,🤙🏻,🤙🏼,🤙🏽,🤙🏾,🤙🏻,🤙🏼,🤙🏽,🤙🏾,🤙🏿 +👈,backhand index pointing left,👈🏻,👈🏻,👈🏼,👈🏻,👈🏼,👈🏽,👈🏻,👈🏼,👈🏽,👈🏾,👈🏻,👈🏼,👈🏽,👈🏾,👈🏿 +👉,backhand index pointing right,👉🏻,👉🏻,👉🏼,👉🏻,👉🏼,👉🏽,👉🏻,👉🏼,👉🏽,👉🏾,👉🏻,👉🏼,👉🏽,👉🏾,👉🏿 +👆,backhand index pointing up,👆🏻,👆🏻,👆🏼,👆🏻,👆🏼,👆🏽,👆🏻,👆🏼,👆🏽,👆🏾,👆🏻,👆🏼,👆🏽,👆🏾,👆🏿 +🖕,middle finger fuck off,🖕🏻,🖕🏻,🖕🏼,🖕🏻,🖕🏼,🖕🏽,🖕🏻,🖕🏼,🖕🏽,🖕🏾,🖕🏻,🖕🏼,🖕🏽,🖕🏾,🖕🏿 +👇,backhand index pointing down,👇🏻,👇🏻,👇🏼,👇🏻,👇🏼,👇🏽,👇🏻,👇🏼,👇🏽,👇🏾,👇🏻,👇🏼,👇🏽,👇🏾,👇🏿 +☝️,index pointing up,☝🏻,☝🏻,☝🏼,☝🏻,☝🏼,☝🏽,☝🏻,☝🏼,☝🏽,☝🏾,☝🏻,☝🏼,☝🏽,☝🏾,☝🏿 +🫵,index pointing at the viewer you,🫵🏻,🫵🏻,🫵🏼,🫵🏻,🫵🏼,🫵🏽,🫵🏻,🫵🏼,🫵🏽,🫵🏾,🫵🏻,🫵🏼,🫵🏽,🫵🏾,🫵🏿 +👍,thumbs up all the best,👍🏻,👍🏻,👍🏼,👍🏻,👍🏼,👍🏽,👍🏻,👍🏼,👍🏽,👍🏾,👍🏻,👍🏼,👍🏽,👍🏾,👍🏿 +👎,thumbs down,👎🏻,👎🏻,👎🏼,👎🏻,👎🏼,👎🏽,👎🏻,👎🏼,👎🏽,👎🏾,👎🏻,👎🏼,👎🏽,👎🏾,👎🏿 +✊,raised fist ,✊🏻,✊🏻,✊🏼,✊🏻,✊🏼,✊🏽,✊🏻,✊🏼,✊🏽,✊🏾,✊🏻,✊🏼,✊🏽,✊🏾,✊🏿 +👊,oncoming fist,👊🏻,👊🏻,👊🏼,👊🏻,👊🏼,👊🏽,👊🏻,👊🏼,👊🏽,👊🏾,👊🏻,👊🏼,👊🏽,👊🏾,👊🏿 +🤛,left-facing fist,🤛🏻,🤛🏻,🤛🏼,🤛🏻,🤛🏼,🤛🏽,🤛🏻,🤛🏼,🤛🏽,🤛🏾,🤛🏻,🤛🏼,🤛🏽,🤛🏾,🤛🏿 +🤜,right-facing fist,🤜🏻,🤜🏻,🤜🏼,🤜🏻,🤜🏼,🤜🏽,🤜🏻,🤜🏼,🤜🏽,🤜🏾,🤜🏻,🤜🏼,🤜🏽,🤜🏾,🤜🏿 +👏,clapping hands,👏🏻,👏🏻,👏🏼,👏🏻,👏🏼,👏🏽,👏🏻,👏🏼,👏🏽,👏🏾,👏🏻,👏🏼,👏🏽,👏🏾,👏🏿 +🙌,raising hands,🙌🏻,🙌🏻,🙌🏼,🙌🏻,🙌🏼,🙌🏽,🙌🏻,🙌🏼,🙌🏽,🙌🏾,🙌🏻,🙌🏼,🙌🏽,🙌🏾,🙌🏿 +🫶,heart hands,🫶🏻,🫶🏻,🫶🏼,🫶🏻,🫶🏼,🫶🏽,🫶🏻,🫶🏼,🫶🏽,🫶🏾,🫶🏻,🫶🏼,🫶🏽,🫶🏾,🫶🏿 +👐,open hands,👐🏻,👐🏻,👐🏼,👐🏻,👐🏼,👐🏽,👐🏻,👐🏼,👐🏽,👐🏾,👐🏻,👐🏼,👐🏽,👐🏾,👐🏿 +🤲,palms up together,🤲🏻,🤲🏻,🤲🏼,🤲🏻,🤲🏼,🤲🏽,🤲🏻,🤲🏼,🤲🏽,🤲🏾,🤲🏻,🤲🏼,🤲🏽,🤲🏾,🤲🏿 +🤝,handshake,🤝🏻,🤝🏻,🤝🏼,🤝🏻,🤝🏼,🤝🏽,🤝🏻,🤝🏼,🤝🏽,🤝🏾 +🙏,folded hands,🙏🏻,🙏🏻,🙏🏼,🙏🏻,🙏🏼,🙏🏽,🙏🏻,🙏🏼,🙏🏽,🙏🏾,🙏🏻,🙏🏼,🙏🏽,🙏🏾,🙏🏿 +✍️,writing hand,✍🏻,✍🏻,✍🏼,✍🏻,✍🏼,✍🏽,✍🏻,✍🏼,✍🏽,✍🏾,✍🏻,✍🏼,✍🏽,✍🏾,✍🏿 +💅,nail polish,💅🏻,💅🏻,💅🏼,💅🏻,💅🏼,💅🏽,💅🏻,💅🏼,💅🏽,💅🏾,💅🏻,💅🏼,💅🏽,💅🏾,💅🏿 +🤳,selfie,🤳🏻,🤳🏻,🤳🏼,🤳🏻,🤳🏼,🤳🏽,🤳🏻,🤳🏼,🤳🏽,🤳🏾,🤳🏻,🤳🏼,🤳🏽,🤳🏾,🤳🏿 +💪,flexed biceps,💪🏻,💪🏻,💪🏼,💪🏻,💪🏼,💪🏽,💪🏻,💪🏼,💪🏽,💪🏾,💪🏻,💪🏼,💪🏽,💪🏾,💪🏿 +🦾,mechanical arm +🦿,mechanical leg +🦵,leg,🦵🏻,🦵🏻,🦵🏼,🦵🏻,🦵🏼,🦵🏽,🦵🏻,🦵🏼,🦵🏽,🦵🏾,🦵🏻,🦵🏼,🦵🏽,🦵🏾,🦵🏿 +🦶,foot,🦶🏻,🦶🏻,🦶🏼,🦶🏻,🦶🏼,🦶🏽,🦶🏻,🦶🏼,🦶🏽,🦶🏾,🦶🏻,🦶🏼,🦶🏽,🦶🏾,🦶🏿 +👂,ear,👂🏻,👂🏻,👂🏼,👂🏻,👂🏼,👂🏽,👂🏻,👂🏼,👂🏽,👂🏾,👂🏻,👂🏼,👂🏽,👂🏾,👂🏿 +🦻,ear with hearing aid,🦻🏻,🦻🏻,🦻🏼,🦻🏻,🦻🏼,🦻🏽,🦻🏻,🦻🏼,🦻🏽,🦻🏾,🦻🏻,🦻🏼,🦻🏽,🦻🏾,🦻🏿 +👃,nose,👃🏻,👃🏻,👃🏼,👃🏻,👃🏼,👃🏽,👃🏻,👃🏼,👃🏽,👃🏾,👃🏻,👃🏼,👃🏽,👃🏾,👃🏿 +🧠,brain +🫀,anatomical heart +🫁,lungs +🦷,tooth +🦴,bone +👀,eyes look +👁️,eye +👅,tongue taste +👄,mouth speak +🫦,biting lip horny +👶,baby,👶🏻,👶🏻,👶🏼,👶🏻,👶🏼,👶🏽,👶🏻,👶🏼,👶🏽,👶🏾,👶🏻,👶🏼,👶🏽,👶🏾,👶🏿 +🧒,child,🧒🏻,🧒🏻,🧒🏼,🧒🏻,🧒🏼,🧒🏽,🧒🏻,🧒🏼,🧒🏽,🧒🏾,🧒🏻,🧒🏼,🧒🏽,🧒🏾,🧒🏿 +👦,boy,👦🏻,👦🏻,👦🏼,👦🏻,👦🏼,👦🏽,👦🏻,👦🏼,👦🏽,👦🏾,👦🏻,👦🏼,👦🏽,👦🏾,👦🏿 +👧,girl,👧🏻,👧🏻,👧🏼,👧🏻,👧🏼,👧🏽,👧🏻,👧🏼,👧🏽,👧🏾,👧🏻,👧🏼,👧🏽,👧🏾,👧🏿 +🧑,person,🧑🏻,🧑🏻,🧑🏼,🧑🏻,🧑🏼,🧑🏽,🧑🏻,🧑🏼,🧑🏽,🧑🏾,🧑🏻,🧑🏼,🧑🏽,🧑🏾,🧑🏿 +👨,man,👨🏻,👨🏻,👨🏼,👨🏻,👨🏼,👨🏽,👨🏻,👨🏼,👨🏽,👨🏾,👨🏻,👨🏼,👨🏽,👨🏾,👨🏿,👨🏻 +👩,woman,🧔‍♀️,🧔🏻‍♀️,🧔🏼‍♀️,🧔🏽‍♀️,🧔🏾‍♀️,🧔🏿‍♀️,🧔‍♀️,🧔🏻‍♀️,🧔🏼‍♀️,🧔🏽‍♀️,🧔🏾‍♀️,🧔🏿‍♀️,👩🏻,🧔‍♀️,🧔🏻‍♀️ +🧓,older person,🧓🏻,🧓🏻,🧓🏼,🧓🏻,🧓🏼,🧓🏽,🧓🏻,🧓🏼,🧓🏽,🧓🏾,🧓🏻,🧓🏼,🧓🏽,🧓🏾,🧓🏿 +👴,old man,👴🏻,👴🏻,👴🏼,👴🏻,👴🏼,👴🏽,👴🏻,👴🏼,👴🏽,👴🏾,👴🏻,👴🏼,👴🏽,👴🏾,👴🏿 +👵,old woman,👵🏻,👵🏻,👵🏼,👵🏻,👵🏼,👵🏽,👵🏻,👵🏼,👵🏽,👵🏾,👵🏻,👵🏼,👵🏽,👵🏾,👵🏿 +🙍,person frowning,🙍🏻,🙍🏻,🙍🏼,🙍🏻,🙍🏼,🙍🏽,🙍🏻,🙍🏼,🙍🏽,🙍🏾,🙍🏻,🙍🏼,🙍🏽,🙍🏾,🙍🏿 +🙍‍♂️,man frowning,🙍🏻‍♂️,🙍🏻‍♂️,🙍🏼‍♂️,🙍🏻‍♂️,🙍🏼‍♂️,🙍🏽‍♂️,🙍🏻‍♂️,🙍🏼‍♂️,🙍🏽‍♂️,🙍🏾‍♂️,🙍🏻‍♂️,🙍🏼‍♂️,🙍🏽‍♂️,🙍🏾‍♂️,🙍🏿‍♂️ +🙍‍♀️,woman frowning,🙍🏻‍♀️,🙍🏻‍♀️,🙍🏼‍♀️,🙍🏻‍♀️,🙍🏼‍♀️,🙍🏽‍♀️,🙍🏻‍♀️,🙍🏼‍♀️,🙍🏽‍♀️,🙍🏾‍♀️,🙍🏻‍♀️,🙍🏼‍♀️,🙍🏽‍♀️,🙍🏾‍♀️,🙍🏿‍♀️ +🙎,person pouting,🙎🏻,🙎🏻,🙎🏼,🙎🏻,🙎🏼,🙎🏽,🙎🏻,🙎🏼,🙎🏽,🙎🏾,🙎🏻,🙎🏼,🙎🏽,🙎🏾,🙎🏿 +🙎‍♂️,man pouting,🙎🏻‍♂️,🙎🏻‍♂️,🙎🏼‍♂️,🙎🏻‍♂️,🙎🏼‍♂️,🙎🏽‍♂️,🙎🏻‍♂️,🙎🏼‍♂️,🙎🏽‍♂️,🙎🏾‍♂️,🙎🏻‍♂️,🙎🏼‍♂️,🙎🏽‍♂️,🙎🏾‍♂️,🙎🏿‍♂️ +🙎‍♀️,woman pouting,🙎🏻‍♀️,🙎🏻‍♀️,🙎🏼‍♀️,🙎🏻‍♀️,🙎🏼‍♀️,🙎🏽‍♀️,🙎🏻‍♀️,🙎🏼‍♀️,🙎🏽‍♀️,🙎🏾‍♀️,🙎🏻‍♀️,🙎🏼‍♀️,🙎🏽‍♀️,🙎🏾‍♀️,🙎🏿‍♀️ +🙅,person gesturing NO,🙅🏻,🙅🏻,🙅🏼,🙅🏻,🙅🏼,🙅🏽,🙅🏻,🙅🏼,🙅🏽,🙅🏾,🙅🏻,🙅🏼,🙅🏽,🙅🏾,🙅🏿 +🙅‍♂️,man gesturing NO,🙅🏻‍♂️,🙅🏻‍♂️,🙅🏼‍♂️,🙅🏻‍♂️,🙅🏼‍♂️,🙅🏽‍♂️,🙅🏻‍♂️,🙅🏼‍♂️,🙅🏽‍♂️,🙅🏾‍♂️,🙅🏻‍♂️,🙅🏼‍♂️,🙅🏽‍♂️,🙅🏾‍♂️,🙅🏿‍♂️ +🙅‍♀️,woman gesturing NO,🙅🏻‍♀️,🙅🏻‍♀️,🙅🏼‍♀️,🙅🏻‍♀️,🙅🏼‍♀️,🙅🏽‍♀️,🙅🏻‍♀️,🙅🏼‍♀️,🙅🏽‍♀️,🙅🏾‍♀️,🙅🏻‍♀️,🙅🏼‍♀️,🙅🏽‍♀️,🙅🏾‍♀️,🙅🏿‍♀️ +🙆,person gesturing OK,🙆🏻,🙆🏻,🙆🏼,🙆🏻,🙆🏼,🙆🏽,🙆🏻,🙆🏼,🙆🏽,🙆🏾,🙆🏻,🙆🏼,🙆🏽,🙆🏾,🙆🏿 +🙆‍♂️,man gesturing OK,🙆🏻‍♂️,🙆🏻‍♂️,🙆🏼‍♂️,🙆🏻‍♂️,🙆🏼‍♂️,🙆🏽‍♂️,🙆🏻‍♂️,🙆🏼‍♂️,🙆🏽‍♂️,🙆🏾‍♂️,🙆🏻‍♂️,🙆🏼‍♂️,🙆🏽‍♂️,🙆🏾‍♂️,🙆🏿‍♂️ +🙆‍♀️,woman gesturing OK,🙆🏻‍♀️,🙆🏻‍♀️,🙆🏼‍♀️,🙆🏻‍♀️,🙆🏼‍♀️,🙆🏽‍♀️,🙆🏻‍♀️,🙆🏼‍♀️,🙆🏽‍♀️,🙆🏾‍♀️,🙆🏻‍♀️,🙆🏼‍♀️,🙆🏽‍♀️,🙆🏾‍♀️,🙆🏿‍♀️ +💁,person tipping hand,💁🏻,💁🏻,💁🏼,💁🏻,💁🏼,💁🏽,💁🏻,💁🏼,💁🏽,💁🏾,💁🏻,💁🏼,💁🏽,💁🏾,💁🏿 +💁‍♂️,man tipping hand,💁🏻‍♂️,💁🏻‍♂️,💁🏼‍♂️,💁🏻‍♂️,💁🏼‍♂️,💁🏽‍♂️,💁🏻‍♂️,💁🏼‍♂️,💁🏽‍♂️,💁🏾‍♂️,💁🏻‍♂️,💁🏼‍♂️,💁🏽‍♂️,💁🏾‍♂️,💁🏿‍♂️ +💁‍♀️,woman tipping hand,💁🏻‍♀️,💁🏻‍♀️,💁🏼‍♀️,💁🏻‍♀️,💁🏼‍♀️,💁🏽‍♀️,💁🏻‍♀️,💁🏼‍♀️,💁🏽‍♀️,💁🏾‍♀️,💁🏻‍♀️,💁🏼‍♀️,💁🏽‍♀️,💁🏾‍♀️,💁🏿‍♀️ +🙋,person raising hand,🙋🏻,🙋🏻,🙋🏼,🙋🏻,🙋🏼,🙋🏽,🙋🏻,🙋🏼,🙋🏽,🙋🏾,🙋🏻,🙋🏼,🙋🏽,🙋🏾,🙋🏿 +🙋‍♂️,man raising hand,🙋🏻‍♂️,🙋🏻‍♂️,🙋🏼‍♂️,🙋🏻‍♂️,🙋🏼‍♂️,🙋🏽‍♂️,🙋🏻‍♂️,🙋🏼‍♂️,🙋🏽‍♂️,🙋🏾‍♂️,🙋🏻‍♂️,🙋🏼‍♂️,🙋🏽‍♂️,🙋🏾‍♂️,🙋🏿‍♂️ +🙋‍♀️,woman raising hand,🙋🏻‍♀️,🙋🏻‍♀️,🙋🏼‍♀️,🙋🏻‍♀️,🙋🏼‍♀️,🙋🏽‍♀️,🙋🏻‍♀️,🙋🏼‍♀️,🙋🏽‍♀️,🙋🏾‍♀️,🙋🏻‍♀️,🙋🏼‍♀️,🙋🏽‍♀️,🙋🏾‍♀️,🙋🏿‍♀️ +🧏,deaf person,🧏🏻,🧏🏻,🧏🏼,🧏🏻,🧏🏼,🧏🏽,🧏🏻,🧏🏼,🧏🏽,🧏🏾,🧏🏻,🧏🏼,🧏🏽,🧏🏾,🧏🏿 +🧏‍♂️,deaf man,🧏🏻‍♂️,🧏🏻‍♂️,🧏🏼‍♂️,🧏🏻‍♂️,🧏🏼‍♂️,🧏🏽‍♂️,🧏🏻‍♂️,🧏🏼‍♂️,🧏🏽‍♂️,🧏🏾‍♂️,🧏🏻‍♂️,🧏🏼‍♂️,🧏🏽‍♂️,🧏🏾‍♂️,🧏🏿‍♂️ +🧏‍♀️,deaf woman,🧏🏻‍♀️,🧏🏻‍♀️,🧏🏼‍♀️,🧏🏻‍♀️,🧏🏼‍♀️,🧏🏽‍♀️,🧏🏻‍♀️,🧏🏼‍♀️,🧏🏽‍♀️,🧏🏾‍♀️,🧏🏻‍♀️,🧏🏼‍♀️,🧏🏽‍♀️,🧏🏾‍♀️,🧏🏿‍♀️ +🙇,person bowing,🙇🏻,🙇🏻,🙇🏼,🙇🏻,🙇🏼,🙇🏽,🙇🏻,🙇🏼,🙇🏽,🙇🏾,🙇🏻,🙇🏼,🙇🏽,🙇🏾,🙇🏿 +🙇‍♂️,man bowing,🙇🏻‍♂️,🙇🏻‍♂️,🙇🏼‍♂️,🙇🏻‍♂️,🙇🏼‍♂️,🙇🏽‍♂️,🙇🏻‍♂️,🙇🏼‍♂️,🙇🏽‍♂️,🙇🏾‍♂️,🙇🏻‍♂️,🙇🏼‍♂️,🙇🏽‍♂️,🙇🏾‍♂️,🙇🏿‍♂️ +🙇‍♀️,woman bowing,🙇🏻‍♀️,🙇🏻‍♀️,🙇🏼‍♀️,🙇🏻‍♀️,🙇🏼‍♀️,🙇🏽‍♀️,🙇🏻‍♀️,🙇🏼‍♀️,🙇🏽‍♀️,🙇🏾‍♀️,🙇🏻‍♀️,🙇🏼‍♀️,🙇🏽‍♀️,🙇🏾‍♀️,🙇🏿‍♀️ +🤦,person facepalming,🤦🏻,🤦🏻,🤦🏼,🤦🏻,🤦🏼,🤦🏽,🤦🏻,🤦🏼,🤦🏽,🤦🏾,🤦🏻,🤦🏼,🤦🏽,🤦🏾,🤦🏿 +🤦‍♂️,man facepalming,🤦🏻‍♂️,🤦🏻‍♂️,🤦🏼‍♂️,🤦🏻‍♂️,🤦🏼‍♂️,🤦🏽‍♂️,🤦🏻‍♂️,🤦🏼‍♂️,🤦🏽‍♂️,🤦🏾‍♂️,🤦🏻‍♂️,🤦🏼‍♂️,🤦🏽‍♂️,🤦🏾‍♂️,🤦🏿‍♂️ +🤦‍♀️,woman facepalming,🤦🏻‍♀️,🤦🏻‍♀️,🤦🏼‍♀️,🤦🏻‍♀️,🤦🏼‍♀️,🤦🏽‍♀️,🤦🏻‍♀️,🤦🏼‍♀️,🤦🏽‍♀️,🤦🏾‍♀️,🤦🏻‍♀️,🤦🏼‍♀️,🤦🏽‍♀️,🤦🏾‍♀️,🤦🏿‍♀️ +🤷,person shrugging,🤷🏻,🤷🏻,🤷🏼,🤷🏻,🤷🏼,🤷🏽,🤷🏻,🤷🏼,🤷🏽,🤷🏾,🤷🏻,🤷🏼,🤷🏽,🤷🏾,🤷🏿 +🤷‍♂️,man shrugging,🤷🏻‍♂️,🤷🏻‍♂️,🤷🏼‍♂️,🤷🏻‍♂️,🤷🏼‍♂️,🤷🏽‍♂️,🤷🏻‍♂️,🤷🏼‍♂️,🤷🏽‍♂️,🤷🏾‍♂️,🤷🏻‍♂️,🤷🏼‍♂️,🤷🏽‍♂️,🤷🏾‍♂️,🤷🏿‍♂️ +🤷‍♀️,woman shrugging,🤷🏻‍♀️,🤷🏻‍♀️,🤷🏼‍♀️,🤷🏻‍♀️,🤷🏼‍♀️,🤷🏽‍♀️,🤷🏻‍♀️,🤷🏼‍♀️,🤷🏽‍♀️,🤷🏾‍♀️,🤷🏻‍♀️,🤷🏼‍♀️,🤷🏽‍♀️,🤷🏾‍♀️,🤷🏿‍♀️ +🧑‍⚕️,health worker,🧑🏻‍⚕️,🧑🏻‍⚕️,🧑🏼‍⚕️,🧑🏻‍⚕️,🧑🏼‍⚕️,🧑🏽‍⚕️,🧑🏻‍⚕️,🧑🏼‍⚕️,🧑🏽‍⚕️,🧑🏾‍⚕️,🧑🏻‍⚕️,🧑🏼‍⚕️,🧑🏽‍⚕️,🧑🏾‍⚕️,🧑🏿‍⚕️ +👨‍⚕️,man health worker,👨🏻‍⚕️,👨🏻‍⚕️,👨🏼‍⚕️,👨🏻‍⚕️,👨🏼‍⚕️,👨🏽‍⚕️,👨🏻‍⚕️,👨🏼‍⚕️,👨🏽‍⚕️,👨🏾‍⚕️,👨🏻‍⚕️,👨🏼‍⚕️,👨🏽‍⚕️,👨🏾‍⚕️,👨🏿‍⚕️ +👩‍⚕️,woman health worker,👩🏻‍⚕️,👩🏻‍⚕️,👩🏼‍⚕️,👩🏻‍⚕️,👩🏼‍⚕️,👩🏽‍⚕️,👩🏻‍⚕️,👩🏼‍⚕️,👩🏽‍⚕️,👩🏾‍⚕️,👩🏻‍⚕️,👩🏼‍⚕️,👩🏽‍⚕️,👩🏾‍⚕️,👩🏿‍⚕️ +🧑‍🎓,student,🧑🏻‍🎓,🧑🏻‍🎓,🧑🏼‍🎓,🧑🏻‍🎓,🧑🏼‍🎓,🧑🏽‍🎓,🧑🏻‍🎓,🧑🏼‍🎓,🧑🏽‍🎓,🧑🏾‍🎓,🧑🏻‍🎓,🧑🏼‍🎓,🧑🏽‍🎓,🧑🏾‍🎓,🧑🏿‍🎓 +👨‍🎓,man student,👨🏻‍🎓,👨🏻‍🎓,👨🏼‍🎓,👨🏻‍🎓,👨🏼‍🎓,👨🏽‍🎓,👨🏻‍🎓,👨🏼‍🎓,👨🏽‍🎓,👨🏾‍🎓,👨🏻‍🎓,👨🏼‍🎓,👨🏽‍🎓,👨🏾‍🎓,👨🏿‍🎓 +👩‍🎓,woman student,👩🏻‍🎓,👩🏻‍🎓,👩🏼‍🎓,👩🏻‍🎓,👩🏼‍🎓,👩🏽‍🎓,👩🏻‍🎓,👩🏼‍🎓,👩🏽‍🎓,👩🏾‍🎓,👩🏻‍🎓,👩🏼‍🎓,👩🏽‍🎓,👩🏾‍🎓,👩🏿‍🎓 +🧑‍🏫,teacher,🧑🏻‍🏫,🧑🏻‍🏫,🧑🏼‍🏫,🧑🏻‍🏫,🧑🏼‍🏫,🧑🏽‍🏫,🧑🏻‍🏫,🧑🏼‍🏫,🧑🏽‍🏫,🧑🏾‍🏫,🧑🏻‍🏫,🧑🏼‍🏫,🧑🏽‍🏫,🧑🏾‍🏫,🧑🏿‍🏫 +👨‍🏫,man teacher,👨🏻‍🏫,👨🏻‍🏫,👨🏼‍🏫,👨🏻‍🏫,👨🏼‍🏫,👨🏽‍🏫,👨🏻‍🏫,👨🏼‍🏫,👨🏽‍🏫,👨🏾‍🏫,👨🏻‍🏫,👨🏼‍🏫,👨🏽‍🏫,👨🏾‍🏫,👨🏿‍🏫 +👩‍🏫,woman teacher,👩🏻‍🏫,👩🏻‍🏫,👩🏼‍🏫,👩🏻‍🏫,👩🏼‍🏫,👩🏽‍🏫,👩🏻‍🏫,👩🏼‍🏫,👩🏽‍🏫,👩🏾‍🏫,👩🏻‍🏫,👩🏼‍🏫,👩🏽‍🏫,👩🏾‍🏫,👩🏿‍🏫 +🧑‍⚖️,judge,🧑🏻‍⚖️,🧑🏻‍⚖️,🧑🏼‍⚖️,🧑🏻‍⚖️,🧑🏼‍⚖️,🧑🏽‍⚖️,🧑🏻‍⚖️,🧑🏼‍⚖️,🧑🏽‍⚖️,🧑🏾‍⚖️,🧑🏻‍⚖️,🧑🏼‍⚖️,🧑🏽‍⚖️,🧑🏾‍⚖️,🧑🏿‍⚖️ +👨‍⚖️,man judge,👨🏻‍⚖️,👨🏻‍⚖️,👨🏼‍⚖️,👨🏻‍⚖️,👨🏼‍⚖️,👨🏽‍⚖️,👨🏻‍⚖️,👨🏼‍⚖️,👨🏽‍⚖️,👨🏾‍⚖️,👨🏻‍⚖️,👨🏼‍⚖️,👨🏽‍⚖️,👨🏾‍⚖️,👨🏿‍⚖️ +👩‍⚖️,woman judge,👩🏻‍⚖️,👩🏻‍⚖️,👩🏼‍⚖️,👩🏻‍⚖️,👩🏼‍⚖️,👩🏽‍⚖️,👩🏻‍⚖️,👩🏼‍⚖️,👩🏽‍⚖️,👩🏾‍⚖️,👩🏻‍⚖️,👩🏼‍⚖️,👩🏽‍⚖️,👩🏾‍⚖️,👩🏿‍⚖️ +🧑‍🌾,farmer,🧑🏻‍🌾,🧑🏻‍🌾,🧑🏼‍🌾,🧑🏻‍🌾,🧑🏼‍🌾,🧑🏽‍🌾,🧑🏻‍🌾,🧑🏼‍🌾,🧑🏽‍🌾,🧑🏾‍🌾,🧑🏻‍🌾,🧑🏼‍🌾,🧑🏽‍🌾,🧑🏾‍🌾,🧑🏿‍🌾 +👨‍🌾,man farmer,👨🏻‍🌾,👨🏻‍🌾,👨🏼‍🌾,👨🏻‍🌾,👨🏼‍🌾,👨🏽‍🌾,👨🏻‍🌾,👨🏼‍🌾,👨🏽‍🌾,👨🏾‍🌾,👨🏻‍🌾,👨🏼‍🌾,👨🏽‍🌾,👨🏾‍🌾,👨🏿‍🌾 +👩‍🌾,woman farmer,👩🏻‍🌾,👩🏻‍🌾,👩🏼‍🌾,👩🏻‍🌾,👩🏼‍🌾,👩🏽‍🌾,👩🏻‍🌾,👩🏼‍🌾,👩🏽‍🌾,👩🏾‍🌾,👩🏻‍🌾,👩🏼‍🌾,👩🏽‍🌾,👩🏾‍🌾,👩🏿‍🌾 +🧑‍🍳,cook,🧑🏻‍🍳,🧑🏻‍🍳,🧑🏼‍🍳,🧑🏻‍🍳,🧑🏼‍🍳,🧑🏽‍🍳,🧑🏻‍🍳,🧑🏼‍🍳,🧑🏽‍🍳,🧑🏾‍🍳,🧑🏻‍🍳,🧑🏼‍🍳,🧑🏽‍🍳,🧑🏾‍🍳,🧑🏿‍🍳 +👨‍🍳,man cook,👨🏻‍🍳,👨🏻‍🍳,👨🏼‍🍳,👨🏻‍🍳,👨🏼‍🍳,👨🏽‍🍳,👨🏻‍🍳,👨🏼‍🍳,👨🏽‍🍳,👨🏾‍🍳,👨🏻‍🍳,👨🏼‍🍳,👨🏽‍🍳,👨🏾‍🍳,👨🏿‍🍳 +👩‍🍳,woman cook,👩🏻‍🍳,👩🏻‍🍳,👩🏼‍🍳,👩🏻‍🍳,👩🏼‍🍳,👩🏽‍🍳,👩🏻‍🍳,👩🏼‍🍳,👩🏽‍🍳,👩🏾‍🍳,👩🏻‍🍳,👩🏼‍🍳,👩🏽‍🍳,👩🏾‍🍳,👩🏿‍🍳 +🧑‍🔧,mechanic,🧑🏻‍🔧,🧑🏻‍🔧,🧑🏼‍🔧,🧑🏻‍🔧,🧑🏼‍🔧,🧑🏽‍🔧,🧑🏻‍🔧,🧑🏼‍🔧,🧑🏽‍🔧,🧑🏾‍🔧,🧑🏻‍🔧,🧑🏼‍🔧,🧑🏽‍🔧,🧑🏾‍🔧,🧑🏿‍🔧 +👨‍🔧,man mechanic,👨🏻‍🔧,👨🏻‍🔧,👨🏼‍🔧,👨🏻‍🔧,👨🏼‍🔧,👨🏽‍🔧,👨🏻‍🔧,👨🏼‍🔧,👨🏽‍🔧,👨🏾‍🔧,👨🏻‍🔧,👨🏼‍🔧,👨🏽‍🔧,👨🏾‍🔧,👨🏿‍🔧 +👩‍🔧,woman mechanic,👩🏻‍🔧,👩🏻‍🔧,👩🏼‍🔧,👩🏻‍🔧,👩🏼‍🔧,👩🏽‍🔧,👩🏻‍🔧,👩🏼‍🔧,👩🏽‍🔧,👩🏾‍🔧,👩🏻‍🔧,👩🏼‍🔧,👩🏽‍🔧,👩🏾‍🔧,👩🏿‍🔧 +🧑‍🏭,factory worker,🧑🏻‍🏭,🧑🏻‍🏭,🧑🏼‍🏭,🧑🏻‍🏭,🧑🏼‍🏭,🧑🏽‍🏭,🧑🏻‍🏭,🧑🏼‍🏭,🧑🏽‍🏭,🧑🏾‍🏭,🧑🏻‍🏭,🧑🏼‍🏭,🧑🏽‍🏭,🧑🏾‍🏭,🧑🏿‍🏭 +👨‍🏭,man factory worker,👨🏻‍🏭,👨🏻‍🏭,👨🏼‍🏭,👨🏻‍🏭,👨🏼‍🏭,👨🏽‍🏭,👨🏻‍🏭,👨🏼‍🏭,👨🏽‍🏭,👨🏾‍🏭,👨🏻‍🏭,👨🏼‍🏭,👨🏽‍🏭,👨🏾‍🏭,👨🏿‍🏭 +👩‍🏭,woman factory worker,👩🏻‍🏭,👩🏻‍🏭,👩🏼‍🏭,👩🏻‍🏭,👩🏼‍🏭,👩🏽‍🏭,👩🏻‍🏭,👩🏼‍🏭,👩🏽‍🏭,👩🏾‍🏭,👩🏻‍🏭,👩🏼‍🏭,👩🏽‍🏭,👩🏾‍🏭,👩🏿‍🏭 +🧑‍💼,office worker,🧑🏻‍💼,🧑🏻‍💼,🧑🏼‍💼,🧑🏻‍💼,🧑🏼‍💼,🧑🏽‍💼,🧑🏻‍💼,🧑🏼‍💼,🧑🏽‍💼,🧑🏾‍💼,🧑🏻‍💼,🧑🏼‍💼,🧑🏽‍💼,🧑🏾‍💼,🧑🏿‍💼 +👨‍💼,man office worker,👨🏻‍💼,👨🏻‍💼,👨🏼‍💼,👨🏻‍💼,👨🏼‍💼,👨🏽‍💼,👨🏻‍💼,👨🏼‍💼,👨🏽‍💼,👨🏾‍💼,👨🏻‍💼,👨🏼‍💼,👨🏽‍💼,👨🏾‍💼,👨🏿‍💼 +👩‍💼,woman office worker,👩🏻‍💼,👩🏻‍💼,👩🏼‍💼,👩🏻‍💼,👩🏼‍💼,👩🏽‍💼,👩🏻‍💼,👩🏼‍💼,👩🏽‍💼,👩🏾‍💼,👩🏻‍💼,👩🏼‍💼,👩🏽‍💼,👩🏾‍💼,👩🏿‍💼 +🧑‍🔬,scientist,🧑🏻‍🔬,🧑🏻‍🔬,🧑🏼‍🔬,🧑🏻‍🔬,🧑🏼‍🔬,🧑🏽‍🔬,🧑🏻‍🔬,🧑🏼‍🔬,🧑🏽‍🔬,🧑🏾‍🔬,🧑🏻‍🔬,🧑🏼‍🔬,🧑🏽‍🔬,🧑🏾‍🔬,🧑🏿‍🔬 +👨‍🔬,man scientist,👨🏻‍🔬,👨🏻‍🔬,👨🏼‍🔬,👨🏻‍🔬,👨🏼‍🔬,👨🏽‍🔬,👨🏻‍🔬,👨🏼‍🔬,👨🏽‍🔬,👨🏾‍🔬,👨🏻‍🔬,👨🏼‍🔬,👨🏽‍🔬,👨🏾‍🔬,👨🏿‍🔬 +👩‍🔬,woman scientist,👩🏻‍🔬,👩🏻‍🔬,👩🏼‍🔬,👩🏻‍🔬,👩🏼‍🔬,👩🏽‍🔬,👩🏻‍🔬,👩🏼‍🔬,👩🏽‍🔬,👩🏾‍🔬,👩🏻‍🔬,👩🏼‍🔬,👩🏽‍🔬,👩🏾‍🔬,👩🏿‍🔬 +🧑‍💻,technologist,🧑🏻‍💻,🧑🏻‍💻,🧑🏼‍💻,🧑🏻‍💻,🧑🏼‍💻,🧑🏽‍💻,🧑🏻‍💻,🧑🏼‍💻,🧑🏽‍💻,🧑🏾‍💻,🧑🏻‍💻,🧑🏼‍💻,🧑🏽‍💻,🧑🏾‍💻,🧑🏿‍💻 +👨‍💻,man technologist,👨🏻‍💻,👨🏻‍💻,👨🏼‍💻,👨🏻‍💻,👨🏼‍💻,👨🏽‍💻,👨🏻‍💻,👨🏼‍💻,👨🏽‍💻,👨🏾‍💻,👨🏻‍💻,👨🏼‍💻,👨🏽‍💻,👨🏾‍💻,👨🏿‍💻 +👩‍💻,woman technologist,👩🏻‍💻,👩🏻‍💻,👩🏼‍💻,👩🏻‍💻,👩🏼‍💻,👩🏽‍💻,👩🏻‍💻,👩🏼‍💻,👩🏽‍💻,👩🏾‍💻,👩🏻‍💻,👩🏼‍💻,👩🏽‍💻,👩🏾‍💻,👩🏿‍💻 +🧑‍🎤,singer,🧑🏻‍🎤,🧑🏻‍🎤,🧑🏼‍🎤,🧑🏻‍🎤,🧑🏼‍🎤,🧑🏽‍🎤,🧑🏻‍🎤,🧑🏼‍🎤,🧑🏽‍🎤,🧑🏾‍🎤,🧑🏻‍🎤,🧑🏼‍🎤,🧑🏽‍🎤,🧑🏾‍🎤,🧑🏿‍🎤 +👨‍🎤,man singer,👨🏻‍🎤,👨🏻‍🎤,👨🏼‍🎤,👨🏻‍🎤,👨🏼‍🎤,👨🏽‍🎤,👨🏻‍🎤,👨🏼‍🎤,👨🏽‍🎤,👨🏾‍🎤,👨🏻‍🎤,👨🏼‍🎤,👨🏽‍🎤,👨🏾‍🎤,👨🏿‍🎤 +👩‍🎤,woman singer,👩🏻‍🎤,👩🏻‍🎤,👩🏼‍🎤,👩🏻‍🎤,👩🏼‍🎤,👩🏽‍🎤,👩🏻‍🎤,👩🏼‍🎤,👩🏽‍🎤,👩🏾‍🎤,👩🏻‍🎤,👩🏼‍🎤,👩🏽‍🎤,👩🏾‍🎤,👩🏿‍🎤 +🧑‍🎨,artist,🧑🏻‍🎨,🧑🏻‍🎨,🧑🏼‍🎨,🧑🏻‍🎨,🧑🏼‍🎨,🧑🏽‍🎨,🧑🏻‍🎨,🧑🏼‍🎨,🧑🏽‍🎨,🧑🏾‍🎨,🧑🏻‍🎨,🧑🏼‍🎨,🧑🏽‍🎨,🧑🏾‍🎨,🧑🏿‍🎨 +👨‍🎨,man artist,👨🏻‍🎨,👨🏻‍🎨,👨🏼‍🎨,👨🏻‍🎨,👨🏼‍🎨,👨🏽‍🎨,👨🏻‍🎨,👨🏼‍🎨,👨🏽‍🎨,👨🏾‍🎨,👨🏻‍🎨,👨🏼‍🎨,👨🏽‍🎨,👨🏾‍🎨,👨🏿‍🎨 +👩‍🎨,woman artist,👩🏻‍🎨,👩🏻‍🎨,👩🏼‍🎨,👩🏻‍🎨,👩🏼‍🎨,👩🏽‍🎨,👩🏻‍🎨,👩🏼‍🎨,👩🏽‍🎨,👩🏾‍🎨,👩🏻‍🎨,👩🏼‍🎨,👩🏽‍🎨,👩🏾‍🎨,👩🏿‍🎨 +🧑‍✈️,pilot,🧑🏻‍✈️,🧑🏻‍✈️,🧑🏼‍✈️,🧑🏻‍✈️,🧑🏼‍✈️,🧑🏽‍✈️,🧑🏻‍✈️,🧑🏼‍✈️,🧑🏽‍✈️,🧑🏾‍✈️,🧑🏻‍✈️,🧑🏼‍✈️,🧑🏽‍✈️,🧑🏾‍✈️,🧑🏿‍✈️ +👨‍✈️,man pilot,👨🏻‍✈️,👨🏻‍✈️,👨🏼‍✈️,👨🏻‍✈️,👨🏼‍✈️,👨🏽‍✈️,👨🏻‍✈️,👨🏼‍✈️,👨🏽‍✈️,👨🏾‍✈️,👨🏻‍✈️,👨🏼‍✈️,👨🏽‍✈️,👨🏾‍✈️,👨🏿‍✈️ +👩‍✈️,woman pilot,👩🏻‍✈️,👩🏻‍✈️,👩🏼‍✈️,👩🏻‍✈️,👩🏼‍✈️,👩🏽‍✈️,👩🏻‍✈️,👩🏼‍✈️,👩🏽‍✈️,👩🏾‍✈️,👩🏻‍✈️,👩🏼‍✈️,👩🏽‍✈️,👩🏾‍✈️,👩🏿‍✈️ +🧑‍🚀,astronaut,🧑🏻‍🚀,🧑🏻‍🚀,🧑🏼‍🚀,🧑🏻‍🚀,🧑🏼‍🚀,🧑🏽‍🚀,🧑🏻‍🚀,🧑🏼‍🚀,🧑🏽‍🚀,🧑🏾‍🚀,🧑🏻‍🚀,🧑🏼‍🚀,🧑🏽‍🚀,🧑🏾‍🚀,🧑🏿‍🚀 +👨‍🚀,man astronaut,👨🏻‍🚀,👨🏻‍🚀,👨🏼‍🚀,👨🏻‍🚀,👨🏼‍🚀,👨🏽‍🚀,👨🏻‍🚀,👨🏼‍🚀,👨🏽‍🚀,👨🏾‍🚀,👨🏻‍🚀,👨🏼‍🚀,👨🏽‍🚀,👨🏾‍🚀,👨🏿‍🚀 +👩‍🚀,woman astronaut,👩🏻‍🚀,👩🏻‍🚀,👩🏼‍🚀,👩🏻‍🚀,👩🏼‍🚀,👩🏽‍🚀,👩🏻‍🚀,👩🏼‍🚀,👩🏽‍🚀,👩🏾‍🚀,👩🏻‍🚀,👩🏼‍🚀,👩🏽‍🚀,👩🏾‍🚀,👩🏿‍🚀 +🧑‍🚒,firefighter,🧑🏻‍🚒,🧑🏻‍🚒,🧑🏼‍🚒,🧑🏻‍🚒,🧑🏼‍🚒,🧑🏽‍🚒,🧑🏻‍🚒,🧑🏼‍🚒,🧑🏽‍🚒,🧑🏾‍🚒,🧑🏻‍🚒,🧑🏼‍🚒,🧑🏽‍🚒,🧑🏾‍🚒,🧑🏿‍🚒 +👨‍🚒,man firefighter,👨🏻‍🚒,👨🏻‍🚒,👨🏼‍🚒,👨🏻‍🚒,👨🏼‍🚒,👨🏽‍🚒,👨🏻‍🚒,👨🏼‍🚒,👨🏽‍🚒,👨🏾‍🚒,👨🏻‍🚒,👨🏼‍🚒,👨🏽‍🚒,👨🏾‍🚒,👨🏿‍🚒 +👩‍🚒,woman firefighter,👩🏻‍🚒,👩🏻‍🚒,👩🏼‍🚒,👩🏻‍🚒,👩🏼‍🚒,👩🏽‍🚒,👩🏻‍🚒,👩🏼‍🚒,👩🏽‍🚒,👩🏾‍🚒,👩🏻‍🚒,👩🏼‍🚒,👩🏽‍🚒,👩🏾‍🚒,👩🏿‍🚒 +👮,police officer,👮🏻,👮🏻,👮🏼,👮🏻,👮🏼,👮🏽,👮🏻,👮🏼,👮🏽,👮🏾,👮🏻,👮🏼,👮🏽,👮🏾,👮🏿 +👮‍♂️,man police officer,👮🏻‍♂️,👮🏻‍♂️,👮🏼‍♂️,👮🏻‍♂️,👮🏼‍♂️,👮🏽‍♂️,👮🏻‍♂️,👮🏼‍♂️,👮🏽‍♂️,👮🏾‍♂️,👮🏻‍♂️,👮🏼‍♂️,👮🏽‍♂️,👮🏾‍♂️,👮🏿‍♂️ +👮‍♀️,woman police officer,👮🏻‍♀️,👮🏻‍♀️,👮🏼‍♀️,👮🏻‍♀️,👮🏼‍♀️,👮🏽‍♀️,👮🏻‍♀️,👮🏼‍♀️,👮🏽‍♀️,👮🏾‍♀️,👮🏻‍♀️,👮🏼‍♀️,👮🏽‍♀️,👮🏾‍♀️,👮🏿‍♀️ +🕵️,detective,🕵🏻,🕵🏻,🕵🏼,🕵🏻,🕵🏼,🕵🏽,🕵🏻,🕵🏼,🕵🏽,🕵🏾,🕵🏻,🕵🏼,🕵🏽,🕵🏾,🕵🏿 +🕵️‍♂️,man detective,🕵🏻‍♂️,🕵🏻‍♂️,🕵🏼‍♂️,🕵🏻‍♂️,🕵🏼‍♂️,🕵🏽‍♂️,🕵🏻‍♂️,🕵🏼‍♂️,🕵🏽‍♂️,🕵🏾‍♂️ +🕵️‍♀️,woman detective,🕵🏻‍♀️,🕵🏻‍♀️,🕵🏼‍♀️,🕵🏻‍♀️,🕵🏼‍♀️,🕵🏽‍♀️,🕵🏻‍♀️,🕵🏼‍♀️,🕵🏽‍♀️,🕵🏾‍♀️ +💂,guard,💂🏻,💂🏻,💂🏼,💂🏻,💂🏼,💂🏽,💂🏻,💂🏼,💂🏽,💂🏾,💂🏻,💂🏼,💂🏽,💂🏾,💂🏿 +💂‍♂️,man guard,💂🏻‍♂️,💂🏻‍♂️,💂🏼‍♂️,💂🏻‍♂️,💂🏼‍♂️,💂🏽‍♂️,💂🏻‍♂️,💂🏼‍♂️,💂🏽‍♂️,💂🏾‍♂️,💂🏻‍♂️,💂🏼‍♂️,💂🏽‍♂️,💂🏾‍♂️,💂🏿‍♂️ +💂‍♀️,woman guard,💂🏻‍♀️,💂🏻‍♀️,💂🏼‍♀️,💂🏻‍♀️,💂🏼‍♀️,💂🏽‍♀️,💂🏻‍♀️,💂🏼‍♀️,💂🏽‍♀️,💂🏾‍♀️,💂🏻‍♀️,💂🏼‍♀️,💂🏽‍♀️,💂🏾‍♀️,💂🏿‍♀️ +🥷,ninja,🥷🏻,🥷🏻,🥷🏼,🥷🏻,🥷🏼,🥷🏽,🥷🏻,🥷🏼,🥷🏽,🥷🏾,🥷🏻,🥷🏼,🥷🏽,🥷🏾,🥷🏿 +👷,construction worker,👷🏻,👷🏻,👷🏼,👷🏻,👷🏼,👷🏽,👷🏻,👷🏼,👷🏽,👷🏾,👷🏻,👷🏼,👷🏽,👷🏾,👷🏿 +👷‍♂️,man construction worker,👷🏻‍♂️,👷🏻‍♂️,👷🏼‍♂️,👷🏻‍♂️,👷🏼‍♂️,👷🏽‍♂️,👷🏻‍♂️,👷🏼‍♂️,👷🏽‍♂️,👷🏾‍♂️,👷🏻‍♂️,👷🏼‍♂️,👷🏽‍♂️,👷🏾‍♂️,👷🏿‍♂️ +👷‍♀️,woman construction worker,👷🏻‍♀️,👷🏻‍♀️,👷🏼‍♀️,👷🏻‍♀️,👷🏼‍♀️,👷🏽‍♀️,👷🏻‍♀️,👷🏼‍♀️,👷🏽‍♀️,👷🏾‍♀️,👷🏻‍♀️,👷🏼‍♀️,👷🏽‍♀️,👷🏾‍♀️,👷🏿‍♀️ +🫅,person with crown,🫅🏻,🫅🏻,🫅🏼,🫅🏻,🫅🏼,🫅🏽,🫅🏻,🫅🏼,🫅🏽,🫅🏾,🫅🏻,🫅🏼,🫅🏽,🫅🏾,🫅🏿 +🤴,prince,🤴🏻,🤴🏻,🤴🏼,🤴🏻,🤴🏼,🤴🏽,🤴🏻,🤴🏼,🤴🏽,🤴🏾,🤴🏻,🤴🏼,🤴🏽,🤴🏾,🤴🏿 +👸,princess,👸🏻,👸🏻,👸🏼,👸🏻,👸🏼,👸🏽,👸🏻,👸🏼,👸🏽,👸🏾,👸🏻,👸🏼,👸🏽,👸🏾,👸🏿 +👳,person wearing turban,👳🏻,👳🏻,👳🏼,👳🏻,👳🏼,👳🏽,👳🏻,👳🏼,👳🏽,👳🏾,👳🏻,👳🏼,👳🏽,👳🏾,👳🏿 +👳‍♂️,man wearing turban,👳🏻‍♂️,👳🏻‍♂️,👳🏼‍♂️,👳🏻‍♂️,👳🏼‍♂️,👳🏽‍♂️,👳🏻‍♂️,👳🏼‍♂️,👳🏽‍♂️,👳🏾‍♂️,👳🏻‍♂️,👳🏼‍♂️,👳🏽‍♂️,👳🏾‍♂️,👳🏿‍♂️ +👳‍♀️,woman wearing turban,👳🏻‍♀️,👳🏻‍♀️,👳🏼‍♀️,👳🏻‍♀️,👳🏼‍♀️,👳🏽‍♀️,👳🏻‍♀️,👳🏼‍♀️,👳🏽‍♀️,👳🏾‍♀️,👳🏻‍♀️,👳🏼‍♀️,👳🏽‍♀️,👳🏾‍♀️,👳🏿‍♀️ +👲,person with skullcap,👲🏻,👲🏻,👲🏼,👲🏻,👲🏼,👲🏽,👲🏻,👲🏼,👲🏽,👲🏾,👲🏻,👲🏼,👲🏽,👲🏾,👲🏿 +🧕,woman with headscarf,🧕🏻,🧕🏻,🧕🏼,🧕🏻,🧕🏼,🧕🏽,🧕🏻,🧕🏼,🧕🏽,🧕🏾,🧕🏻,🧕🏼,🧕🏽,🧕🏾,🧕🏿 +🤵,person in tuxedo,🤵🏻,🤵🏻,🤵🏼,🤵🏻,🤵🏼,🤵🏽,🤵🏻,🤵🏼,🤵🏽,🤵🏾,🤵🏻,🤵🏼,🤵🏽,🤵🏾,🤵🏿 +🤵‍♂️,man in tuxedo,🤵🏻‍♂️,🤵🏻‍♂️,🤵🏼‍♂️,🤵🏻‍♂️,🤵🏼‍♂️,🤵🏽‍♂️,🤵🏻‍♂️,🤵🏼‍♂️,🤵🏽‍♂️,🤵🏾‍♂️,🤵🏻‍♂️,🤵🏼‍♂️,🤵🏽‍♂️,🤵🏾‍♂️,🤵🏿‍♂️ +🤵‍♀️,woman in tuxedo,🤵🏻‍♀️,🤵🏻‍♀️,🤵🏼‍♀️,🤵🏻‍♀️,🤵🏼‍♀️,🤵🏽‍♀️,🤵🏻‍♀️,🤵🏼‍♀️,🤵🏽‍♀️,🤵🏾‍♀️,🤵🏻‍♀️,🤵🏼‍♀️,🤵🏽‍♀️,🤵🏾‍♀️,🤵🏿‍♀️ +👰,person with veil,👰🏻,👰🏻,👰🏼,👰🏻,👰🏼,👰🏽,👰🏻,👰🏼,👰🏽,👰🏾,👰🏻,👰🏼,👰🏽,👰🏾,👰🏿 +👰‍♂️,man with veil,👰🏻‍♂️,👰🏻‍♂️,👰🏼‍♂️,👰🏻‍♂️,👰🏼‍♂️,👰🏽‍♂️,👰🏻‍♂️,👰🏼‍♂️,👰🏽‍♂️,👰🏾‍♂️,👰🏻‍♂️,👰🏼‍♂️,👰🏽‍♂️,👰🏾‍♂️,👰🏿‍♂️ +👰‍♀️,woman with veil,👰🏻‍♀️,👰🏻‍♀️,👰🏼‍♀️,👰🏻‍♀️,👰🏼‍♀️,👰🏽‍♀️,👰🏻‍♀️,👰🏼‍♀️,👰🏽‍♀️,👰🏾‍♀️,👰🏻‍♀️,👰🏼‍♀️,👰🏽‍♀️,👰🏾‍♀️,👰🏿‍♀️ +🤰,pregnant woman,🤰🏻,🤰🏻,🤰🏼,🤰🏻,🤰🏼,🤰🏽,🤰🏻,🤰🏼,🤰🏽,🤰🏾,🤰🏻,🤰🏼,🤰🏽,🤰🏾,🤰🏿 +🫃,pregnant man,🫃🏻,🫃🏻,🫃🏼,🫃🏻,🫃🏼,🫃🏽,🫃🏻,🫃🏼,🫃🏽,🫃🏾,🫃🏻,🫃🏼,🫃🏽,🫃🏾,🫃🏿 +🫄,pregnant person,🫄🏻,🫄🏻,🫄🏼,🫄🏻,🫄🏼,🫄🏽,🫄🏻,🫄🏼,🫄🏽,🫄🏾,🫄🏻,🫄🏼,🫄🏽,🫄🏾,🫄🏿 +🤱,breast-feeding,🤱🏻,🤱🏻,🤱🏼,🤱🏻,🤱🏼,🤱🏽,🤱🏻,🤱🏼,🤱🏽,🤱🏾,🤱🏻,🤱🏼,🤱🏽,🤱🏾,🤱🏿 +👩‍🍼,woman feeding baby,👩🏻‍🍼,👩🏻‍🍼,👩🏼‍🍼,👩🏻‍🍼,👩🏼‍🍼,👩🏽‍🍼,👩🏻‍🍼,👩🏼‍🍼,👩🏽‍🍼,👩🏾‍🍼,👩🏻‍🍼,👩🏼‍🍼,👩🏽‍🍼,👩🏾‍🍼,👩🏿‍🍼 +👨‍🍼,man feeding baby,👨🏻‍🍼,👨🏻‍🍼,👨🏼‍🍼,👨🏻‍🍼,👨🏼‍🍼,👨🏽‍🍼,👨🏻‍🍼,👨🏼‍🍼,👨🏽‍🍼,👨🏾‍🍼,👨🏻‍🍼,👨🏼‍🍼,👨🏽‍🍼,👨🏾‍🍼,👨🏿‍🍼 +🧑‍🍼,person feeding baby,🧑🏻‍🍼,🧑🏻‍🍼,🧑🏼‍🍼,🧑🏻‍🍼,🧑🏼‍🍼,🧑🏽‍🍼,🧑🏻‍🍼,🧑🏼‍🍼,🧑🏽‍🍼,🧑🏾‍🍼,🧑🏻‍🍼,🧑🏼‍🍼,🧑🏽‍🍼,🧑🏾‍🍼,🧑🏿‍🍼 +👼,baby angel,👼🏻,👼🏻,👼🏼,👼🏻,👼🏼,👼🏽,👼🏻,👼🏼,👼🏽,👼🏾,👼🏻,👼🏼,👼🏽,👼🏾,👼🏿 +🎅,Santa Claus,🎅🏻,🎅🏻,🎅🏼,🎅🏻,🎅🏼,🎅🏽,🎅🏻,🎅🏼,🎅🏽,🎅🏾,🎅🏻,🎅🏼,🎅🏽,🎅🏾,🎅🏿 +🤶,Mrs. Claus,🤶🏻,🤶🏻,🤶🏼,🤶🏻,🤶🏼,🤶🏽,🤶🏻,🤶🏼,🤶🏽,🤶🏾,🤶🏻,🤶🏼,🤶🏽,🤶🏾,🤶🏿 +🧑‍🎄,mx claus,🧑🏻‍🎄,🧑🏻‍🎄,🧑🏼‍🎄,🧑🏻‍🎄,🧑🏼‍🎄,🧑🏽‍🎄,🧑🏻‍🎄,🧑🏼‍🎄,🧑🏽‍🎄,🧑🏾‍🎄,🧑🏻‍🎄,🧑🏼‍🎄,🧑🏽‍🎄,🧑🏾‍🎄,🧑🏿‍🎄 +🦸,superhero,🦸🏻,🦸🏻,🦸🏼,🦸🏻,🦸🏼,🦸🏽,🦸🏻,🦸🏼,🦸🏽,🦸🏾,🦸🏻,🦸🏼,🦸🏽,🦸🏾,🦸🏿 +🦸‍♂️,man superhero,🦸🏻‍♂️,🦸🏻‍♂️,🦸🏼‍♂️,🦸🏻‍♂️,🦸🏼‍♂️,🦸🏽‍♂️,🦸🏻‍♂️,🦸🏼‍♂️,🦸🏽‍♂️,🦸🏾‍♂️,🦸🏻‍♂️,🦸🏼‍♂️,🦸🏽‍♂️,🦸🏾‍♂️,🦸🏿‍♂️ +🦸‍♀️,woman superhero,🦸🏻‍♀️,🦸🏻‍♀️,🦸🏼‍♀️,🦸🏻‍♀️,🦸🏼‍♀️,🦸🏽‍♀️,🦸🏻‍♀️,🦸🏼‍♀️,🦸🏽‍♀️,🦸🏾‍♀️,🦸🏻‍♀️,🦸🏼‍♀️,🦸🏽‍♀️,🦸🏾‍♀️,🦸🏿‍♀️ +🦹,supervillain,🦹🏻,🦹🏻,🦹🏼,🦹🏻,🦹🏼,🦹🏽,🦹🏻,🦹🏼,🦹🏽,🦹🏾,🦹🏻,🦹🏼,🦹🏽,🦹🏾,🦹🏿 +🦹‍♂️,man supervillain,🦹🏻‍♂️,🦹🏻‍♂️,🦹🏼‍♂️,🦹🏻‍♂️,🦹🏼‍♂️,🦹🏽‍♂️,🦹🏻‍♂️,🦹🏼‍♂️,🦹🏽‍♂️,🦹🏾‍♂️,🦹🏻‍♂️,🦹🏼‍♂️,🦹🏽‍♂️,🦹🏾‍♂️,🦹🏿‍♂️ +🦹‍♀️,woman supervillain,🦹🏻‍♀️,🦹🏻‍♀️,🦹🏼‍♀️,🦹🏻‍♀️,🦹🏼‍♀️,🦹🏽‍♀️,🦹🏻‍♀️,🦹🏼‍♀️,🦹🏽‍♀️,🦹🏾‍♀️,🦹🏻‍♀️,🦹🏼‍♀️,🦹🏽‍♀️,🦹🏾‍♀️,🦹🏿‍♀️ +🧙,mage,🧙🏻,🧙🏻,🧙🏼,🧙🏻,🧙🏼,🧙🏽,🧙🏻,🧙🏼,🧙🏽,🧙🏾,🧙🏻,🧙🏼,🧙🏽,🧙🏾,🧙🏿 +🧙‍♂️,man mage,🧙🏻‍♂️,🧙🏻‍♂️,🧙🏼‍♂️,🧙🏻‍♂️,🧙🏼‍♂️,🧙🏽‍♂️,🧙🏻‍♂️,🧙🏼‍♂️,🧙🏽‍♂️,🧙🏾‍♂️,🧙🏻‍♂️,🧙🏼‍♂️,🧙🏽‍♂️,🧙🏾‍♂️,🧙🏿‍♂️ +🧙‍♀️,woman mage,🧙🏻‍♀️,🧙🏻‍♀️,🧙🏼‍♀️,🧙🏻‍♀️,🧙🏼‍♀️,🧙🏽‍♀️,🧙🏻‍♀️,🧙🏼‍♀️,🧙🏽‍♀️,🧙🏾‍♀️,🧙🏻‍♀️,🧙🏼‍♀️,🧙🏽‍♀️,🧙🏾‍♀️,🧙🏿‍♀️ +🧚,fairy,🧚🏻,🧚🏻,🧚🏼,🧚🏻,🧚🏼,🧚🏽,🧚🏻,🧚🏼,🧚🏽,🧚🏾,🧚🏻,🧚🏼,🧚🏽,🧚🏾,🧚🏿 +🧚‍♂️,man fairy,🧚🏻‍♂️,🧚🏻‍♂️,🧚🏼‍♂️,🧚🏻‍♂️,🧚🏼‍♂️,🧚🏽‍♂️,🧚🏻‍♂️,🧚🏼‍♂️,🧚🏽‍♂️,🧚🏾‍♂️,🧚🏻‍♂️,🧚🏼‍♂️,🧚🏽‍♂️,🧚🏾‍♂️,🧚🏿‍♂️ +🧚‍♀️,woman fairy,🧚🏻‍♀️,🧚🏻‍♀️,🧚🏼‍♀️,🧚🏻‍♀️,🧚🏼‍♀️,🧚🏽‍♀️,🧚🏻‍♀️,🧚🏼‍♀️,🧚🏽‍♀️,🧚🏾‍♀️,🧚🏻‍♀️,🧚🏼‍♀️,🧚🏽‍♀️,🧚🏾‍♀️,🧚🏿‍♀️ +🧛,vampire,🧛🏻,🧛🏻,🧛🏼,🧛🏻,🧛🏼,🧛🏽,🧛🏻,🧛🏼,🧛🏽,🧛🏾,🧛🏻,🧛🏼,🧛🏽,🧛🏾,🧛🏿 +🧛‍♂️,man vampire,🧛🏻‍♂️,🧛🏻‍♂️,🧛🏼‍♂️,🧛🏻‍♂️,🧛🏼‍♂️,🧛🏽‍♂️,🧛🏻‍♂️,🧛🏼‍♂️,🧛🏽‍♂️,🧛🏾‍♂️,🧛🏻‍♂️,🧛🏼‍♂️,🧛🏽‍♂️,🧛🏾‍♂️,🧛🏿‍♂️ +🧛‍♀️,woman vampire,🧛🏻‍♀️,🧛🏻‍♀️,🧛🏼‍♀️,🧛🏻‍♀️,🧛🏼‍♀️,🧛🏽‍♀️,🧛🏻‍♀️,🧛🏼‍♀️,🧛🏽‍♀️,🧛🏾‍♀️,🧛🏻‍♀️,🧛🏼‍♀️,🧛🏽‍♀️,🧛🏾‍♀️,🧛🏿‍♀️ +🧜,merperson,🧜🏻,🧜🏻,🧜🏼,🧜🏻,🧜🏼,🧜🏽,🧜🏻,🧜🏼,🧜🏽,🧜🏾,🧜🏻,🧜🏼,🧜🏽,🧜🏾,🧜🏿 +🧜‍♂️,merman,🧜🏻‍♂️,🧜🏻‍♂️,🧜🏼‍♂️,🧜🏻‍♂️,🧜🏼‍♂️,🧜🏽‍♂️,🧜🏻‍♂️,🧜🏼‍♂️,🧜🏽‍♂️,🧜🏾‍♂️,🧜🏻‍♂️,🧜🏼‍♂️,🧜🏽‍♂️,🧜🏾‍♂️,🧜🏿‍♂️ +🧜‍♀️,mermaid,🧜🏻‍♀️,🧜🏻‍♀️,🧜🏼‍♀️,🧜🏻‍♀️,🧜🏼‍♀️,🧜🏽‍♀️,🧜🏻‍♀️,🧜🏼‍♀️,🧜🏽‍♀️,🧜🏾‍♀️,🧜🏻‍♀️,🧜🏼‍♀️,🧜🏽‍♀️,🧜🏾‍♀️,🧜🏿‍♀️ +🧝,elf,🧝🏻,🧝🏻,🧝🏼,🧝🏻,🧝🏼,🧝🏽,🧝🏻,🧝🏼,🧝🏽,🧝🏾,🧝🏻,🧝🏼,🧝🏽,🧝🏾,🧝🏿 +🧝‍♂️,man elf,🧝🏻‍♂️,🧝🏻‍♂️,🧝🏼‍♂️,🧝🏻‍♂️,🧝🏼‍♂️,🧝🏽‍♂️,🧝🏻‍♂️,🧝🏼‍♂️,🧝🏽‍♂️,🧝🏾‍♂️,🧝🏻‍♂️,🧝🏼‍♂️,🧝🏽‍♂️,🧝🏾‍♂️,🧝🏿‍♂️ +🧝‍♀️,woman elf,🧝🏻‍♀️,🧝🏻‍♀️,🧝🏼‍♀️,🧝🏻‍♀️,🧝🏼‍♀️,🧝🏽‍♀️,🧝🏻‍♀️,🧝🏼‍♀️,🧝🏽‍♀️,🧝🏾‍♀️,🧝🏻‍♀️,🧝🏼‍♀️,🧝🏽‍♀️,🧝🏾‍♀️,🧝🏿‍♀️ +🧞,genie +🧞‍♂️,man genie +🧞‍♀️,woman genie +🧟,zombie +🧟‍♂️,man zombie +🧟‍♀️,woman zombie +🧌,troll +💆,person getting massage,💆🏻,💆🏻,💆🏼,💆🏻,💆🏼,💆🏽,💆🏻,💆🏼,💆🏽,💆🏾,💆🏻,💆🏼,💆🏽,💆🏾,💆🏿 +💆‍♂️,man getting massage,💆🏻‍♂️,💆🏻‍♂️,💆🏼‍♂️,💆🏻‍♂️,💆🏼‍♂️,💆🏽‍♂️,💆🏻‍♂️,💆🏼‍♂️,💆🏽‍♂️,💆🏾‍♂️,💆🏻‍♂️,💆🏼‍♂️,💆🏽‍♂️,💆🏾‍♂️,💆🏿‍♂️ +💆‍♀️,woman getting massage,💆🏻‍♀️,💆🏻‍♀️,💆🏼‍♀️,💆🏻‍♀️,💆🏼‍♀️,💆🏽‍♀️,💆🏻‍♀️,💆🏼‍♀️,💆🏽‍♀️,💆🏾‍♀️,💆🏻‍♀️,💆🏼‍♀️,💆🏽‍♀️,💆🏾‍♀️,💆🏿‍♀️ +💇,person getting haircut,💇🏻,💇🏻,💇🏼,💇🏻,💇🏼,💇🏽,💇🏻,💇🏼,💇🏽,💇🏾,💇🏻,💇🏼,💇🏽,💇🏾,💇🏿 +💇‍♂️,man getting haircut,💇🏻‍♂️,💇🏻‍♂️,💇🏼‍♂️,💇🏻‍♂️,💇🏼‍♂️,💇🏽‍♂️,💇🏻‍♂️,💇🏼‍♂️,💇🏽‍♂️,💇🏾‍♂️,💇🏻‍♂️,💇🏼‍♂️,💇🏽‍♂️,💇🏾‍♂️,💇🏿‍♂️ +💇‍♀️,woman getting haircut,💇🏻‍♀️,💇🏻‍♀️,💇🏼‍♀️,💇🏻‍♀️,💇🏼‍♀️,💇🏽‍♀️,💇🏻‍♀️,💇🏼‍♀️,💇🏽‍♀️,💇🏾‍♀️,💇🏻‍♀️,💇🏼‍♀️,💇🏽‍♀️,💇🏾‍♀️,💇🏿‍♀️ +🚶,person walking,🚶🏻,🚶🏻,🚶🏼,🚶🏻,🚶🏼,🚶🏽,🚶🏻,🚶🏼,🚶🏽,🚶🏾,🚶🏻,🚶🏼,🚶🏽,🚶🏾,🚶🏿 +🚶‍♂️,man walking,🚶🏻‍♂️,🚶🏻‍♂️,🚶🏼‍♂️,🚶🏻‍♂️,🚶🏼‍♂️,🚶🏽‍♂️,🚶🏻‍♂️,🚶🏼‍♂️,🚶🏽‍♂️,🚶🏾‍♂️,🚶🏻‍♂️,🚶🏼‍♂️,🚶🏽‍♂️,🚶🏾‍♂️,🚶🏿‍♂️ +🚶‍♀️,woman walking,🚶🏻‍♀️,🚶🏻‍♀️,🚶🏼‍♀️,🚶🏻‍♀️,🚶🏼‍♀️,🚶🏽‍♀️,🚶🏻‍♀️,🚶🏼‍♀️,🚶🏽‍♀️,🚶🏾‍♀️,🚶🏻‍♀️,🚶🏼‍♀️,🚶🏽‍♀️,🚶🏾‍♀️,🚶🏿‍♀️ +🧍,person standing,🧍🏻,🧍🏻,🧍🏼,🧍🏻,🧍🏼,🧍🏽,🧍🏻,🧍🏼,🧍🏽,🧍🏾,🧍🏻,🧍🏼,🧍🏽,🧍🏾,🧍🏿 +🧍‍♂️,man standing,🧍🏻‍♂️,🧍🏻‍♂️,🧍🏼‍♂️,🧍🏻‍♂️,🧍🏼‍♂️,🧍🏽‍♂️,🧍🏻‍♂️,🧍🏼‍♂️,🧍🏽‍♂️,🧍🏾‍♂️,🧍🏻‍♂️,🧍🏼‍♂️,🧍🏽‍♂️,🧍🏾‍♂️,🧍🏿‍♂️ +🧍‍♀️,woman standing,🧍🏻‍♀️,🧍🏻‍♀️,🧍🏼‍♀️,🧍🏻‍♀️,🧍🏼‍♀️,🧍🏽‍♀️,🧍🏻‍♀️,🧍🏼‍♀️,🧍🏽‍♀️,🧍🏾‍♀️,🧍🏻‍♀️,🧍🏼‍♀️,🧍🏽‍♀️,🧍🏾‍♀️,🧍🏿‍♀️ +🧎,person kneeling,🧎🏻,🧎🏻,🧎🏼,🧎🏻,🧎🏼,🧎🏽,🧎🏻,🧎🏼,🧎🏽,🧎🏾,🧎🏻,🧎🏼,🧎🏽,🧎🏾,🧎🏿 +🧎‍♂️,man kneeling,🧎🏻‍♂️,🧎🏻‍♂️,🧎🏼‍♂️,🧎🏻‍♂️,🧎🏼‍♂️,🧎🏽‍♂️,🧎🏻‍♂️,🧎🏼‍♂️,🧎🏽‍♂️,🧎🏾‍♂️,🧎🏻‍♂️,🧎🏼‍♂️,🧎🏽‍♂️,🧎🏾‍♂️,🧎🏿‍♂️ +🧎‍♀️,woman kneeling,🧎🏻‍♀️,🧎🏻‍♀️,🧎🏼‍♀️,🧎🏻‍♀️,🧎🏼‍♀️,🧎🏽‍♀️,🧎🏻‍♀️,🧎🏼‍♀️,🧎🏽‍♀️,🧎🏾‍♀️,🧎🏻‍♀️,🧎🏼‍♀️,🧎🏽‍♀️,🧎🏾‍♀️,🧎🏿‍♀️ +🧑‍🦯,person with white cane,🧑🏻‍🦯,🧑🏻‍🦯,🧑🏼‍🦯,🧑🏻‍🦯,🧑🏼‍🦯,🧑🏽‍🦯,🧑🏻‍🦯,🧑🏼‍🦯,🧑🏽‍🦯,🧑🏾‍🦯,🧑🏻‍🦯,🧑🏼‍🦯,🧑🏽‍🦯,🧑🏾‍🦯,🧑🏿‍🦯 +👨‍🦯,man with white cane,👨🏻‍🦯,👨🏻‍🦯,👨🏼‍🦯,👨🏻‍🦯,👨🏼‍🦯,👨🏽‍🦯,👨🏻‍🦯,👨🏼‍🦯,👨🏽‍🦯,👨🏾‍🦯,👨🏻‍🦯,👨🏼‍🦯,👨🏽‍🦯,👨🏾‍🦯,👨🏿‍🦯 +👩‍🦯,woman with white cane,👩🏻‍🦯,👩🏻‍🦯,👩🏼‍🦯,👩🏻‍🦯,👩🏼‍🦯,👩🏽‍🦯,👩🏻‍🦯,👩🏼‍🦯,👩🏽‍🦯,👩🏾‍🦯,👩🏻‍🦯,👩🏼‍🦯,👩🏽‍🦯,👩🏾‍🦯,👩🏿‍🦯 +🧑‍🦼,person in motorized wheelchair,🧑🏻‍🦼,🧑🏻‍🦼,🧑🏼‍🦼,🧑🏻‍🦼,🧑🏼‍🦼,🧑🏽‍🦼,🧑🏻‍🦼,🧑🏼‍🦼,🧑🏽‍🦼,🧑🏾‍🦼,🧑🏻‍🦼,🧑🏼‍🦼,🧑🏽‍🦼,🧑🏾‍🦼,🧑🏿‍🦼 +👨‍🦼,man in motorized wheelchair,👨🏻‍🦼,👨🏻‍🦼,👨🏼‍🦼,👨🏻‍🦼,👨🏼‍🦼,👨🏽‍🦼,👨🏻‍🦼,👨🏼‍🦼,👨🏽‍🦼,👨🏾‍🦼,👨🏻‍🦼,👨🏼‍🦼,👨🏽‍🦼,👨🏾‍🦼,👨🏿‍🦼 +👩‍🦼,woman in motorized wheelchair,👩🏻‍🦼,👩🏻‍🦼,👩🏼‍🦼,👩🏻‍🦼,👩🏼‍🦼,👩🏽‍🦼,👩🏻‍🦼,👩🏼‍🦼,👩🏽‍🦼,👩🏾‍🦼,👩🏻‍🦼,👩🏼‍🦼,👩🏽‍🦼,👩🏾‍🦼,👩🏿‍🦼 +🧑‍🦽,person in manual wheelchair,🧑🏻‍🦽,🧑🏻‍🦽,🧑🏼‍🦽,🧑🏻‍🦽,🧑🏼‍🦽,🧑🏽‍🦽,🧑🏻‍🦽,🧑🏼‍🦽,🧑🏽‍🦽,🧑🏾‍🦽,🧑🏻‍🦽,🧑🏼‍🦽,🧑🏽‍🦽,🧑🏾‍🦽,🧑🏿‍🦽 +👨‍🦽,man in manual wheelchair,👨🏻‍🦽,👨🏻‍🦽,👨🏼‍🦽,👨🏻‍🦽,👨🏼‍🦽,👨🏽‍🦽,👨🏻‍🦽,👨🏼‍🦽,👨🏽‍🦽,👨🏾‍🦽,👨🏻‍🦽,👨🏼‍🦽,👨🏽‍🦽,👨🏾‍🦽,👨🏿‍🦽 +👩‍🦽,woman in manual wheelchair,👩🏻‍🦽,👩🏻‍🦽,👩🏼‍🦽,👩🏻‍🦽,👩🏼‍🦽,👩🏽‍🦽,👩🏻‍🦽,👩🏼‍🦽,👩🏽‍🦽,👩🏾‍🦽,👩🏻‍🦽,👩🏼‍🦽,👩🏽‍🦽,👩🏾‍🦽,👩🏿‍🦽 +🏃,person running,🏃🏻,🏃🏻,🏃🏼,🏃🏻,🏃🏼,🏃🏽,🏃🏻,🏃🏼,🏃🏽,🏃🏾,🏃🏻,🏃🏼,🏃🏽,🏃🏾,🏃🏿 +🏃‍♂️,man running,🏃🏻‍♂️,🏃🏻‍♂️,🏃🏼‍♂️,🏃🏻‍♂️,🏃🏼‍♂️,🏃🏽‍♂️,🏃🏻‍♂️,🏃🏼‍♂️,🏃🏽‍♂️,🏃🏾‍♂️,🏃🏻‍♂️,🏃🏼‍♂️,🏃🏽‍♂️,🏃🏾‍♂️,🏃🏿‍♂️ +🏃‍♀️,woman running,🏃🏻‍♀️,🏃🏻‍♀️,🏃🏼‍♀️,🏃🏻‍♀️,🏃🏼‍♀️,🏃🏽‍♀️,🏃🏻‍♀️,🏃🏼‍♀️,🏃🏽‍♀️,🏃🏾‍♀️,🏃🏻‍♀️,🏃🏼‍♀️,🏃🏽‍♀️,🏃🏾‍♀️,🏃🏿‍♀️ +💃,woman dancing,💃🏻,💃🏻,💃🏼,💃🏻,💃🏼,💃🏽,💃🏻,💃🏼,💃🏽,💃🏾,💃🏻,💃🏼,💃🏽,💃🏾,💃🏿 +🕺,man dancing,🕺🏻,🕺🏻,🕺🏼,🕺🏻,🕺🏼,🕺🏽,🕺🏻,🕺🏼,🕺🏽,🕺🏾,🕺🏻,🕺🏼,🕺🏽,🕺🏾,🕺🏿 +🕴️,person in suit levitating,🕴🏻,🕴🏻,🕴🏼,🕴🏻,🕴🏼,🕴🏽,🕴🏻,🕴🏼,🕴🏽,🕴🏾,🕴🏻,🕴🏼,🕴🏽,🕴🏾,🕴🏿 +👯,people with bunny ears +👯‍♂️,men with bunny ears +👯‍♀️,women with bunny ears +🧖,person in steamy room,🧖🏻,🧖🏻,🧖🏼,🧖🏻,🧖🏼,🧖🏽,🧖🏻,🧖🏼,🧖🏽,🧖🏾,🧖🏻,🧖🏼,🧖🏽,🧖🏾,🧖🏿 +🧖‍♂️,man in steamy room,🧖🏻‍♂️,🧖🏻‍♂️,🧖🏼‍♂️,🧖🏻‍♂️,🧖🏼‍♂️,🧖🏽‍♂️,🧖🏻‍♂️,🧖🏼‍♂️,🧖🏽‍♂️,🧖🏾‍♂️,🧖🏻‍♂️,🧖🏼‍♂️,🧖🏽‍♂️,🧖🏾‍♂️,🧖🏿‍♂️ +🧖‍♀️,woman in steamy room,🧖🏻‍♀️,🧖🏻‍♀️,🧖🏼‍♀️,🧖🏻‍♀️,🧖🏼‍♀️,🧖🏽‍♀️,🧖🏻‍♀️,🧖🏼‍♀️,🧖🏽‍♀️,🧖🏾‍♀️,🧖🏻‍♀️,🧖🏼‍♀️,🧖🏽‍♀️,🧖🏾‍♀️,🧖🏿‍♀️ +🧗,person climbing,🧗🏻,🧗🏻,🧗🏼,🧗🏻,🧗🏼,🧗🏽,🧗🏻,🧗🏼,🧗🏽,🧗🏾,🧗🏻,🧗🏼,🧗🏽,🧗🏾,🧗🏿 +🧗‍♂️,man climbing,🧗🏻‍♂️,🧗🏻‍♂️,🧗🏼‍♂️,🧗🏻‍♂️,🧗🏼‍♂️,🧗🏽‍♂️,🧗🏻‍♂️,🧗🏼‍♂️,🧗🏽‍♂️,🧗🏾‍♂️,🧗🏻‍♂️,🧗🏼‍♂️,🧗🏽‍♂️,🧗🏾‍♂️,🧗🏿‍♂️ +🧗‍♀️,woman climbing,🧗🏻‍♀️,🧗🏻‍♀️,🧗🏼‍♀️,🧗🏻‍♀️,🧗🏼‍♀️,🧗🏽‍♀️,🧗🏻‍♀️,🧗🏼‍♀️,🧗🏽‍♀️,🧗🏾‍♀️,🧗🏻‍♀️,🧗🏼‍♀️,🧗🏽‍♀️,🧗🏾‍♀️,🧗🏿‍♀️ +🤺,person fencing +🏇,horse racing,🏇🏻,🏇🏻,🏇🏼,🏇🏻,🏇🏼,🏇🏽,🏇🏻,🏇🏼,🏇🏽,🏇🏾,🏇🏻,🏇🏼,🏇🏽,🏇🏾,🏇🏿 +⛷️,skier +🏂,snowboarder,🏂🏻,🏂🏻,🏂🏼,🏂🏻,🏂🏼,🏂🏽,🏂🏻,🏂🏼,🏂🏽,🏂🏾,🏂🏻,🏂🏼,🏂🏽,🏂🏾,🏂🏿 +🏌️,person golfing,🏌🏻,🏌🏻,🏌🏼,🏌🏻,🏌🏼,🏌🏽,🏌🏻,🏌🏼,🏌🏽,🏌🏾,🏌🏻,🏌🏼,🏌🏽,🏌🏾,🏌🏿 +🏌️‍♂️,man golfing,🏌🏻‍♂️,🏌🏻‍♂️,🏌🏼‍♂️,🏌🏻‍♂️,🏌🏼‍♂️,🏌🏽‍♂️,🏌🏻‍♂️,🏌🏼‍♂️,🏌🏽‍♂️,🏌🏾‍♂️,🏌🏻‍♂️ +🏌️‍♀️,woman golfing,🏌🏻‍♀️,🏌🏻‍♀️,🏌🏼‍♀️,🏌🏻‍♀️,🏌🏼‍♀️,🏌🏽‍♀️,🏌🏻‍♀️,🏌🏼‍♀️,🏌🏽‍♀️,🏌🏾‍♀️,🏌🏻‍♀️ +🏄,person surfing,🏄🏻,🏄🏻,🏄🏼,🏄🏻,🏄🏼,🏄🏽,🏄🏻,🏄🏼,🏄🏽,🏄🏾,🏄🏻,🏄🏼,🏄🏽,🏄🏾,🏄🏿 +🏄‍♂️,man surfing,🏄🏻‍♂️,🏄🏻‍♂️,🏄🏼‍♂️,🏄🏻‍♂️,🏄🏼‍♂️,🏄🏽‍♂️,🏄🏻‍♂️,🏄🏼‍♂️,🏄🏽‍♂️,🏄🏾‍♂️,🏄🏻‍♂️,🏄🏼‍♂️,🏄🏽‍♂️,🏄🏾‍♂️,🏄🏿‍♂️ +🏄‍♀️,woman surfing,🏄🏻‍♀️,🏄🏻‍♀️,🏄🏼‍♀️,🏄🏻‍♀️,🏄🏼‍♀️,🏄🏽‍♀️,🏄🏻‍♀️,🏄🏼‍♀️,🏄🏽‍♀️,🏄🏾‍♀️,🏄🏻‍♀️,🏄🏼‍♀️,🏄🏽‍♀️,🏄🏾‍♀️,🏄🏿‍♀️ +🚣,person rowing boat,🚣🏻,🚣🏻,🚣🏼,🚣🏻,🚣🏼,🚣🏽,🚣🏻,🚣🏼,🚣🏽,🚣🏾,🚣🏻,🚣🏼,🚣🏽,🚣🏾,🚣🏿 +🚣‍♂️,man rowing boat,🚣🏻‍♂️,🚣🏻‍♂️,🚣🏼‍♂️,🚣🏻‍♂️,🚣🏼‍♂️,🚣🏽‍♂️,🚣🏻‍♂️,🚣🏼‍♂️,🚣🏽‍♂️,🚣🏾‍♂️,🚣🏻‍♂️,🚣🏼‍♂️,🚣🏽‍♂️,🚣🏾‍♂️,🚣🏿‍♂️ +🚣‍♀️,woman rowing boat,🚣🏻‍♀️,🚣🏻‍♀️,🚣🏼‍♀️,🚣🏻‍♀️,🚣🏼‍♀️,🚣🏽‍♀️,🚣🏻‍♀️,🚣🏼‍♀️,🚣🏽‍♀️,🚣🏾‍♀️,🚣🏻‍♀️,🚣🏼‍♀️,🚣🏽‍♀️,🚣🏾‍♀️,🚣🏿‍♀️ +🏊,person swimming,🏊🏻,🏊🏻,🏊🏼,🏊🏻,🏊🏼,🏊🏽,🏊🏻,🏊🏼,🏊🏽,🏊🏾,🏊🏻,🏊🏼,🏊🏽,🏊🏾,🏊🏿 +🏊‍♂️,man swimming,🏊🏻‍♂️,🏊🏻‍♂️,🏊🏼‍♂️,🏊🏻‍♂️,🏊🏼‍♂️,🏊🏽‍♂️,🏊🏻‍♂️,🏊🏼‍♂️,🏊🏽‍♂️,🏊🏾‍♂️,🏊🏻‍♂️,🏊🏼‍♂️,🏊🏽‍♂️,🏊🏾‍♂️,🏊🏿‍♂️ +🏊‍♀️,woman swimming,🏊🏻‍♀️,🏊🏻‍♀️,🏊🏼‍♀️,🏊🏻‍♀️,🏊🏼‍♀️,🏊🏽‍♀️,🏊🏻‍♀️,🏊🏼‍♀️,🏊🏽‍♀️,🏊🏾‍♀️,🏊🏻‍♀️,🏊🏼‍♀️,🏊🏽‍♀️,🏊🏾‍♀️,🏊🏿‍♀️ +⛹️,person bouncing ball,⛹🏻,⛹🏻,⛹🏼,⛹🏻,⛹🏼,⛹🏽,⛹🏻,⛹🏼,⛹🏽 +⛹️‍♂️,man bouncing ball,⛹🏻‍♂️,⛹🏻‍♂️,⛹🏼‍♂️,⛹🏻‍♂️,⛹🏼‍♂️,⛹🏽‍♂️,⛹🏻‍♂️ +⛹️‍♀️,woman bouncing ball,⛹🏻‍♀️,⛹🏻‍♀️,⛹🏼‍♀️,⛹🏻‍♀️,⛹🏼‍♀️,⛹🏽‍♀️,⛹🏻‍♀️ +🏋️,person lifting weights,🏋🏻,🏋🏻,🏋🏼,🏋🏻,🏋🏼,🏋🏽,🏋🏻,🏋🏼,🏋🏽,🏋🏾 +🏋️‍♂️,man lifting weights,🏋🏻‍♂️,🏋🏻‍♂️,🏋🏼‍♂️,🏋🏻‍♂️,🏋🏼‍♂️,🏋🏽‍♂️,🏋🏻‍♂️,🏋🏼‍♂️ +🏋️‍♀️,woman lifting weights,🏋🏻‍♀️,🏋🏻‍♀️,🏋🏼‍♀️,🏋🏻‍♀️,🏋🏼‍♀️,🏋🏽‍♀️,🏋🏻‍♀️,🏋🏼‍♀️ +🚴,person biking,🚴🏻,🚴🏻,🚴🏼,🚴🏻,🚴🏼,🚴🏽,🚴🏻,🚴🏼,🚴🏽,🚴🏾,🚴🏻,🚴🏼,🚴🏽,🚴🏾,🚴🏿 +🚴‍♂️,man biking,🚴🏻‍♂️,🚴🏻‍♂️,🚴🏼‍♂️,🚴🏻‍♂️,🚴🏼‍♂️,🚴🏽‍♂️,🚴🏻‍♂️,🚴🏼‍♂️,🚴🏽‍♂️,🚴🏾‍♂️,🚴🏻‍♂️,🚴🏼‍♂️,🚴🏽‍♂️,🚴🏾‍♂️,🚴🏿‍♂️ +🚴‍♀️,woman biking,🚴🏻‍♀️,🚴🏻‍♀️,🚴🏼‍♀️,🚴🏻‍♀️,🚴🏼‍♀️,🚴🏽‍♀️,🚴🏻‍♀️,🚴🏼‍♀️,🚴🏽‍♀️,🚴🏾‍♀️,🚴🏻‍♀️,🚴🏼‍♀️,🚴🏽‍♀️,🚴🏾‍♀️,🚴🏿‍♀️ +🚵,person mountain biking,🚵🏻,🚵🏻,🚵🏼,🚵🏻,🚵🏼,🚵🏽,🚵🏻,🚵🏼,🚵🏽,🚵🏾,🚵🏻,🚵🏼,🚵🏽,🚵🏾,🚵🏿 +🚵‍♂️,man mountain biking,🚵🏻‍♂️,🚵🏻‍♂️,🚵🏼‍♂️,🚵🏻‍♂️,🚵🏼‍♂️,🚵🏽‍♂️,🚵🏻‍♂️,🚵🏼‍♂️,🚵🏽‍♂️,🚵🏾‍♂️,🚵🏻‍♂️,🚵🏼‍♂️,🚵🏽‍♂️,🚵🏾‍♂️,🚵🏿‍♂️ +🚵‍♀️,woman mountain biking,🚵🏻‍♀️,🚵🏻‍♀️,🚵🏼‍♀️,🚵🏻‍♀️,🚵🏼‍♀️,🚵🏽‍♀️,🚵🏻‍♀️,🚵🏼‍♀️,🚵🏽‍♀️,🚵🏾‍♀️,🚵🏻‍♀️,🚵🏼‍♀️,🚵🏽‍♀️,🚵🏾‍♀️,🚵🏿‍♀️ +🤸,person cartwheeling,🤸🏻,🤸🏻,🤸🏼,🤸🏻,🤸🏼,🤸🏽,🤸🏻,🤸🏼,🤸🏽,🤸🏾,🤸🏻,🤸🏼,🤸🏽,🤸🏾,🤸🏿 +🤸‍♂️,man cartwheeling,🤸🏻‍♂️,🤸🏻‍♂️,🤸🏼‍♂️,🤸🏻‍♂️,🤸🏼‍♂️,🤸🏽‍♂️,🤸🏻‍♂️,🤸🏼‍♂️,🤸🏽‍♂️,🤸🏾‍♂️,🤸🏻‍♂️,🤸🏼‍♂️,🤸🏽‍♂️,🤸🏾‍♂️,🤸🏿‍♂️ +🤸‍♀️,woman cartwheeling,🤸🏻‍♀️,🤸🏻‍♀️,🤸🏼‍♀️,🤸🏻‍♀️,🤸🏼‍♀️,🤸🏽‍♀️,🤸🏻‍♀️,🤸🏼‍♀️,🤸🏽‍♀️,🤸🏾‍♀️,🤸🏻‍♀️,🤸🏼‍♀️,🤸🏽‍♀️,🤸🏾‍♀️,🤸🏿‍♀️ +🤼,people wrestling +🤼‍♂️,men wrestling +🤼‍♀️,women wrestling +🤽,person playing water polo,🤽🏻,🤽🏻,🤽🏼,🤽🏻,🤽🏼,🤽🏽,🤽🏻,🤽🏼,🤽🏽,🤽🏾,🤽🏻,🤽🏼,🤽🏽,🤽🏾,🤽🏿 +🤽‍♂️,man playing water polo,🤽🏻‍♂️,🤽🏻‍♂️,🤽🏼‍♂️,🤽🏻‍♂️,🤽🏼‍♂️,🤽🏽‍♂️,🤽🏻‍♂️,🤽🏼‍♂️,🤽🏽‍♂️,🤽🏾‍♂️,🤽🏻‍♂️,🤽🏼‍♂️,🤽🏽‍♂️,🤽🏾‍♂️,🤽🏿‍♂️ +🤽‍♀️,woman playing water polo,🤽🏻‍♀️,🤽🏻‍♀️,🤽🏼‍♀️,🤽🏻‍♀️,🤽🏼‍♀️,🤽🏽‍♀️,🤽🏻‍♀️,🤽🏼‍♀️,🤽🏽‍♀️,🤽🏾‍♀️,🤽🏻‍♀️,🤽🏼‍♀️,🤽🏽‍♀️,🤽🏾‍♀️,🤽🏿‍♀️ +🤾,person playing handball,🤾🏻,🤾🏻,🤾🏼,🤾🏻,🤾🏼,🤾🏽,🤾🏻,🤾🏼,🤾🏽,🤾🏾,🤾🏻,🤾🏼,🤾🏽,🤾🏾,🤾🏿 +🤾‍♂️,man playing handball,🤾🏻‍♂️,🤾🏻‍♂️,🤾🏼‍♂️,🤾🏻‍♂️,🤾🏼‍♂️,🤾🏽‍♂️,🤾🏻‍♂️,🤾🏼‍♂️,🤾🏽‍♂️,🤾🏾‍♂️,🤾🏻‍♂️,🤾🏼‍♂️,🤾🏽‍♂️,🤾🏾‍♂️,🤾🏿‍♂️ +🤾‍♀️,woman playing handball,🤾🏻‍♀️,🤾🏻‍♀️,🤾🏼‍♀️,🤾🏻‍♀️,🤾🏼‍♀️,🤾🏽‍♀️,🤾🏻‍♀️,🤾🏼‍♀️,🤾🏽‍♀️,🤾🏾‍♀️,🤾🏻‍♀️,🤾🏼‍♀️,🤾🏽‍♀️,🤾🏾‍♀️,🤾🏿‍♀️ +🤹,person juggling,🤹🏻,🤹🏻,🤹🏼,🤹🏻,🤹🏼,🤹🏽,🤹🏻,🤹🏼,🤹🏽,🤹🏾,🤹🏻,🤹🏼,🤹🏽,🤹🏾,🤹🏿 +🤹‍♂️,man juggling,🤹🏻‍♂️,🤹🏻‍♂️,🤹🏼‍♂️,🤹🏻‍♂️,🤹🏼‍♂️,🤹🏽‍♂️,🤹🏻‍♂️,🤹🏼‍♂️,🤹🏽‍♂️,🤹🏾‍♂️,🤹🏻‍♂️,🤹🏼‍♂️,🤹🏽‍♂️,🤹🏾‍♂️,🤹🏿‍♂️ +🤹‍♀️,woman juggling,🤹🏻‍♀️,🤹🏻‍♀️,🤹🏼‍♀️,🤹🏻‍♀️,🤹🏼‍♀️,🤹🏽‍♀️,🤹🏻‍♀️,🤹🏼‍♀️,🤹🏽‍♀️,🤹🏾‍♀️,🤹🏻‍♀️,🤹🏼‍♀️,🤹🏽‍♀️,🤹🏾‍♀️,🤹🏿‍♀️ +🧘,person in lotus position,🧘🏻,🧘🏻,🧘🏼,🧘🏻,🧘🏼,🧘🏽,🧘🏻,🧘🏼,🧘🏽,🧘🏾,🧘🏻,🧘🏼,🧘🏽,🧘🏾,🧘🏿 +🧘‍♂️,man in lotus position,🧘🏻‍♂️,🧘🏻‍♂️,🧘🏼‍♂️,🧘🏻‍♂️,🧘🏼‍♂️,🧘🏽‍♂️,🧘🏻‍♂️,🧘🏼‍♂️,🧘🏽‍♂️,🧘🏾‍♂️,🧘🏻‍♂️,🧘🏼‍♂️,🧘🏽‍♂️,🧘🏾‍♂️,🧘🏿‍♂️ +🧘‍♀️,woman in lotus position,🧘🏻‍♀️,🧘🏻‍♀️,🧘🏼‍♀️,🧘🏻‍♀️,🧘🏼‍♀️,🧘🏽‍♀️,🧘🏻‍♀️,🧘🏼‍♀️,🧘🏽‍♀️,🧘🏾‍♀️,🧘🏻‍♀️,🧘🏼‍♀️,🧘🏽‍♀️,🧘🏾‍♀️,🧘🏿‍♀️ +🛀,person taking bath,🛀🏻,🛀🏻,🛀🏼,🛀🏻,🛀🏼,🛀🏽,🛀🏻,🛀🏼,🛀🏽,🛀🏾,🛀🏻,🛀🏼,🛀🏽,🛀🏾,🛀🏿 +🛌,person in bed,🛌🏻,🛌🏻,🛌🏼,🛌🏻,🛌🏼,🛌🏽,🛌🏻,🛌🏼,🛌🏽,🛌🏾,🛌🏻,🛌🏼,🛌🏽,🛌🏾,🛌🏿 +🧑‍🤝‍🧑,people holding hands,🧑🏻‍🤝‍🧑🏻,🧑🏻‍🤝‍🧑🏻,🧑🏻‍🤝‍🧑🏼,🧑🏻‍🤝‍🧑🏻,🧑🏻‍🤝‍🧑🏼,🧑🏻‍🤝‍🧑🏽,🧑🏻‍🤝‍🧑🏻,🧑🏻‍🤝‍🧑🏼,🧑🏻‍🤝‍🧑🏽,🧑🏻‍🤝‍🧑🏾,🧑🏻‍🤝‍🧑🏻,🧑🏻‍🤝‍🧑🏼,🧑🏻‍🤝‍🧑🏽,🧑🏻‍🤝‍🧑🏾,🧑🏻‍🤝‍🧑🏿,🧑🏻‍🤝‍🧑🏻,🧑🏻‍🤝‍🧑🏼,🧑🏻‍🤝‍🧑🏽,🧑🏻‍🤝‍🧑🏾 +👭,women holding hands,👭🏻,👭🏻,👩🏻‍🤝‍👩🏼,👭🏻,👩🏻‍🤝‍👩🏼,👩🏻‍🤝‍👩🏽,👭🏻,👩🏻‍🤝‍👩🏼,👩🏻‍🤝‍👩🏽,👩🏻‍🤝‍👩🏾,👭🏻,👩🏻‍🤝‍👩🏼,👩🏻‍🤝‍👩🏽,👩🏻‍🤝‍👩🏾,👩🏻‍🤝‍👩🏿,👭🏻,👩🏻‍🤝‍👩🏼,👩🏻‍🤝‍👩🏽,👩🏻‍🤝‍👩🏾‍ +👫,woman and man holding hands,👫🏻,👫🏻,👩🏻‍🤝‍👨🏼,👫🏻,👩🏻‍🤝‍👨🏼,👩🏻‍🤝‍👨🏽,👫🏻,👩🏻‍🤝‍👨🏼,👩🏻‍🤝‍👨🏽,👩🏻‍🤝‍👨🏾,👫🏻,👩🏻‍🤝‍👨🏼,👩🏻‍🤝‍👨🏽,👩🏻‍🤝‍👨🏾,👩🏻‍🤝‍👨🏿,👫🏻,👩🏻‍🤝‍👨🏼 +👬,men holding hands,👬🏻,👬🏻,👨🏻‍🤝‍👨🏼,👬🏻,👨🏻‍🤝‍👨🏼,👨🏻‍🤝‍👨🏽,👬🏻,👨🏻‍🤝‍👨🏼,👨🏻‍🤝‍👨🏽,👨🏻‍🤝‍👨🏾,👬🏻,👨🏻‍🤝‍👨🏼,👨🏻‍🤝‍👨🏽,👨🏻‍🤝‍👨🏾,👨🏻‍🤝‍👨🏿,👬🏻,👨🏻‍🤝‍👨🏼,👨🏻‍🤝‍👨🏽,👨🏻‍🤝‍👨🏾,👨🏻‍🤝‍👨🏿,👨🏼‍🤝‍👨🏻,👬🏻 +💏,kiss,💏🏻,💏🏻,💏🏼,💏🏻,💏🏼,💏🏽,💏🏻,💏🏼,💏🏽,💏🏾,💏🏻,💏🏼,💏🏽,💏🏾,💏🏿,💏🏻,💏🏼,💏🏽,💏🏾,💏🏿,🧑🏻‍❤️‍💋‍🧑🏼,💏🏻,💏🏼,💏🏽,💏🏾,💏🏿 +💑,couple with heart,💑🏻,💑🏻,💑🏼,💑🏻,💑🏼,💑🏽,💑🏻,💑🏼,💑🏽,💑🏾,💑🏻,💑🏼,💑🏽,💑🏾,💑🏿,💑🏻,💑🏼,💑🏽,💑🏾,💑🏿,🧑🏻‍❤️‍🧑🏼,💑🏻,💑🏼 +👪,family,👨‍👩‍👦,👨‍👩‍👦,👨‍👩‍👧,👨‍👩‍👦,👨‍👩‍👧,👨‍👩‍👧‍👦,👨‍👩‍👦,👨‍👩‍👧,👨‍👩‍👧‍👦,👨‍👩‍👦‍👦,👨‍👩‍👦,👨‍👩‍👧,👨‍👩‍👧‍👦,👨‍👩‍👦‍👦,👨‍👩‍👧‍👧,👨‍👩‍👦,👨‍👩‍👧,👨‍👩‍👧‍👦,👨‍👩‍👦‍👦,👨‍👩‍👧‍👧,👨‍👨‍👦,👨‍👩‍👦,👨‍👩‍👧,👨‍👩‍👧‍👦,👨‍👩‍👦‍👦,👨‍👩‍👧‍👧,👨‍👨‍👦,👨‍👨‍👧,👨‍👩‍👦 +🗣️,speaking head +👤,bust in silhouette +👥,busts in silhouette +🫂,people hugging +👣,footprints diff --git a/emojipicker/src/main/res/raw/emoji_category_symbols.csv b/emojipicker/src/main/res/raw/emoji_category_symbols.csv new file mode 100644 index 000000000..09bd4b5df --- /dev/null +++ b/emojipicker/src/main/res/raw/emoji_category_symbols.csv @@ -0,0 +1,210 @@ +🏧,ATM sign +🚮,litter in bin sign +🚰,potable water +♿,wheelchair symbol +🚹,men’s room +🚺,women’s room +🚻,restroom +🚼,baby symbol +🚾,water closet +🛂,passport control +🛃,customs +🛄,baggage claim +🛅,left luggage +⚠️,warning +🚸,children crossing +⛔,no entry +🚫,prohibited +🚳,no bicycles +🚭,no smoking +🚯,no littering +🚱,non-potable water +🚷,no pedestrians +📵,no mobile phones +🔞,no one under eighteen +☢️,radioactive +☣️,biohazard +⬆️,up arrow +↗️,up-right arrow +➡️,right arrow +↘️,down-right arrow +⬇️,down arrow +↙️,down-left arrow +⬅️,left arrow +↖️,up-left arrow +↕️,up-down arrow +↔️,left-right arrow +↩️,right arrow curving left +↪️,left arrow curving right +⤴️,right arrow curving up +⤵️,right arrow curving down +🔃,clockwise vertical arrows +🔄,counterclockwise arrows button +🔙,BACK arrow +🔚,END arrow +🔛,ON! arrow +🔜,SOON arrow +🔝,TOP arrow +🛐,place of worship +⚛️,atom symbol +🕉️,om +✡️,star of David +☸️,wheel of dharma +☯️,yin yang +✝️,latin cross +☦️,orthodox cross +☪️,star and crescent +☮️,peace symbol +🕎,menorah +🔯,dotted six-pointed star +🪯,khanda +♈,Aries +♉,Taurus +♊,Gemini +♋,Cancer +♌,Leo +♍,Virgo +♎,Libra +♏,Scorpio +♐,Sagittarius +♑,Capricorn +♒,Aquarius +♓,Pisces +⛎,Ophiuchus +🔀,shuffle tracks button +🔁,repeat button +🔂,repeat single button +▶️,play button +⏩,fast-forward button +⏭️,next track button +⏯️,play or pause button +◀️,reverse button +⏪,fast reverse button +⏮️,last track button +🔼,upwards button +⏫,fast up button +🔽,downwards button +⏬,fast down button +⏸️,pause button +⏹️,stop button +⏺️,record button +⏏️,eject button +🎦,cinema +🔅,dim button +🔆,bright button +📶,antenna bars +🛜,wireless +📳,vibration mode +📴,mobile phone off +♀️,female sign +♂️,male sign +⚧️,transgender symbol +✖️,multiply +➕,plus +➖,minus +➗,divide +🟰,heavy equals sign +♾️,infinity +‼️,double exclamation mark +⁉️,exclamation question mark +❓,red question mark +❔,white question mark +❕,white exclamation mark +❗,red exclamation mark +〰️,wavy dash +💱,currency exchange +💲,heavy dollar sign +⚕️,medical symbol +♻️,recycling symbol +⚜️,fleur-de-lis +🔱,trident emblem +📛,name badge +🔰,Japanese symbol for beginner +⭕,hollow red circle +✅,check mark button +☑️,check box with check +✔️,check mark +❌,cross mark +❎,cross mark button +➰,curly loop +➿,double curly loop +〽️,part alternation mark +✳️,eight-spoked asterisk +✴️,eight-pointed star +❇️,sparkle +©️,copyright +®️,registered +™️,trade mark +🔠,input latin uppercase +🔡,input latin lowercase +🔢,input numbers +🔣,input symbols +🔤,input latin letters +🅰️,A button (blood type) +🆎,AB button (blood type) +🅱️,B button (blood type) +🆑,CL button +🆒,COOL button +🆓,FREE button +ℹ️,information +🆔,ID button +Ⓜ️,circled M +🆕,NEW button +🆖,NG button +🅾️,O button (blood type) +🆗,OK button +🅿️,P button +🆘,SOS button +🆙,UP! button +🆚,VS button +🈁,Japanese “here” button +🈂️,Japanese “service charge” button +🈷️,Japanese “monthly amount” button +🈶,Japanese “not free of charge” button +🈯,Japanese “reserved” button +🉐,Japanese “bargain” button +🈹,Japanese “discount” button +🈚,Japanese “free of charge” button +🈲,Japanese “prohibited” button +🉑,Japanese “acceptable” button +🈸,Japanese “application” button +🈴,Japanese “passing grade” button +🈳,Japanese “vacancy” button +㊗️,Japanese “congratulations” button +㊙️,Japanese “secret” button +🈺,Japanese “open for business” button +🈵,Japanese “no vacancy” button +🔴,red circle +🟠,orange circle +🟡,yellow circle +🟢,green circle +🔵,blue circle +🟣,purple circle +🟤,brown circle +⚫,black circle +⚪,white circle +🟥,red square +🟧,orange square +🟨,yellow square +🟩,green square +🟦,blue square +🟪,purple square +🟫,brown square +⬛,black large square +⬜,white large square +◼️,black medium square +◻️,white medium square +◾,black medium-small square +◽,white medium-small square +▪️,black small square +▫️,white small square +🔶,large orange diamond +🔷,large blue diamond +🔸,small orange diamond +🔹,small blue diamond +🔺,red triangle pointed up +🔻,red triangle pointed down +💠,diamond with a dot +🔘,radio button +🔳,white square button +🔲,black square button diff --git a/emojipicker/src/main/res/raw/emoji_category_travel_places.csv b/emojipicker/src/main/res/raw/emoji_category_travel_places.csv new file mode 100644 index 000000000..f7e303b1e --- /dev/null +++ b/emojipicker/src/main/res/raw/emoji_category_travel_places.csv @@ -0,0 +1,218 @@ +🌍,globe showing Europe-Africa +🌎,globe showing Americas +🌏,globe showing Asia-Australia +🌐,globe with meridians +🗺️,world map +🗾,map of Japan +🧭,compass +🏔️,snow-capped mountain +⛰️,mountain +🌋,volcano +🗻,mount fuji +🏕️,camping +🏖️,beach with umbrella +🏜️,desert +🏝️,desert island +🏞️,national park +🏟️,stadium +🏛️,classical building +🏗️,building construction +🧱,brick +🪨,rock +🪵,wood +🛖,hut +🏘️,houses +🏚️,derelict house +🏠,house +🏡,house with garden +🏢,office building +🏣,Japanese post office +🏤,post office +🏥,hospital +🏦,bank +🏨,hotel +🏩,love hotel +🏪,convenience store +🏫,school +🏬,department store +🏭,factory +🏯,Japanese castle +🏰,castle +💒,wedding +🗼,Tokyo tower +🗽,Statue of Liberty +⛪,church +🕌,mosque +🛕,hindu temple +🕍,synagogue +⛩️,shinto shrine +🕋,kaaba +⛲,fountain +⛺,tent +🌁,foggy +🌃,night with stars +🏙️,cityscape +🌄,sunrise over mountains +🌅,sunrise +🌆,cityscape at dusk +🌇,sunset +🌉,bridge at night +♨️,hot springs +🎠,carousel horse +🛝,playground slide +🎡,ferris wheel +🎢,roller coaster +💈,barber pole +🎪,circus tent +🚂,locomotive +🚃,railway car +🚄,high-speed train +🚅,bullet train +🚆,train +🚇,metro +🚈,light rail +🚉,station +🚊,tram +🚝,monorail +🚞,mountain railway +🚋,tram car +🚌,bus +🚍,oncoming bus +🚎,trolleybus +🚐,minibus +🚑,ambulance +🚒,fire engine +🚓,police car +🚔,oncoming police car +🚕,taxi +🚖,oncoming taxi +🚗,automobile +🚘,oncoming automobile +🚙,sport utility vehicle +🛻,pickup truck +🚚,delivery truck +🚛,articulated lorry +🚜,tractor +🏎️,racing car +🏍️,motorcycle +🛵,motor scooter +🦽,manual wheelchair +🦼,motorized wheelchair +🛺,auto rickshaw +🚲,bicycle +🛴,kick scooter +🛹,skateboard +🛼,roller skate +🚏,bus stop +🛣️,motorway +🛤️,railway track +🛢️,oil drum +⛽,fuel pump +🛞,wheel +🚨,police car light +🚥,horizontal traffic light +🚦,vertical traffic light +🛑,stop sign +🚧,construction +⚓,anchor +🛟,ring buoy +⛵,sailboat +🛶,canoe +🚤,speedboat +🛳️,passenger ship +⛴️,ferry +🛥️,motor boat +🚢,ship +✈️,airplane +🛩️,small airplane +🛫,airplane departure +🛬,airplane arrival +🪂,parachute +💺,seat +🚁,helicopter +🚟,suspension railway +🚠,mountain cableway +🚡,aerial tramway +🛰️,satellite +🚀,rocket +🛸,flying saucer +🛎️,bellhop bell +🧳,luggage +⌛,hourglass done +⏳,hourglass not done +⌚,watch +⏰,alarm clock +⏱️,stopwatch +⏲️,timer clock +🕰️,mantelpiece clock +🕛,twelve o’clock +🕧,twelve-thirty +🕐,one o’clock +🕜,one-thirty +🕑,two o’clock +🕝,two-thirty +🕒,three o’clock +🕞,three-thirty +🕓,four o’clock +🕟,four-thirty +🕔,five o’clock +🕠,five-thirty +🕕,six o’clock +🕡,six-thirty +🕖,seven o’clock +🕢,seven-thirty +🕗,eight o’clock +🕣,eight-thirty +🕘,nine o’clock +🕤,nine-thirty +🕙,ten o’clock +🕥,ten-thirty +🕚,eleven o’clock +🕦,eleven-thirty +🌑,new moon +🌒,waxing crescent moon +🌓,first quarter moon +🌔,waxing gibbous moon +🌕,full moon +🌖,waning gibbous moon +🌗,last quarter moon +🌘,waning crescent moon +🌙,crescent moon +🌚,new moon face +🌛,first quarter moon face +🌜,last quarter moon face +🌡️,thermometer +☀️,sun +🌝,full moon face +🌞,sun with face +🪐,ringed planet +⭐,star +🌟,glowing star +🌠,shooting star +🌌,milky way +☁️,cloud +⛅,sun behind cloud +⛈️,cloud with lightning and rain +🌤️,sun behind small cloud +🌥️,sun behind large cloud +🌦️,sun behind rain cloud +🌧️,cloud with rain +🌨️,cloud with snow +🌩️,cloud with lightning +🌪️,tornado +🌫️,fog +🌬️,wind face +🌀,cyclone +🌈,rainbow +🌂,closed umbrella +☂️,umbrella +☔,umbrella with rain drops +⛱️,umbrella on ground +⚡,high voltage +❄️,snowflake +☃️,snowman +⛄,snowman without snow +☄️,comet +🔥,fire +💧,droplet +🌊,water wave diff --git a/emojipicker/src/main/res/values-af/strings.xml b/emojipicker/src/main/res/values-af/strings.xml new file mode 100644 index 000000000..ef7bb7c44 --- /dev/null +++ b/emojipicker/src/main/res/values-af/strings.xml @@ -0,0 +1,42 @@ + + + + + "ONLANGS GEBRUIK" + "EMOSIEKONE EN EMOSIES" + "MENSE" + "DIERE EN NATUUR" + "KOS EN DRINKGOED" + "REIS EN PLEKKE" + "AKTIWITEITE EN GELEENTHEDE" + "VOORWERPE" + "SIMBOLE" + "VLAE" + "Geen emosiekone beskikbaar nie" + "Jy het nog geen emosiekone gebruik nie" + "emosiekoon-tweerigtingoorskakelaar" + "rigting waarin emosiekoon wys is gewissel" + "emosiekoonvariantkieser" + "%1$s en %2$s" + "skadu" + "ligte velkleur" + "mediumligte velkleur" + "medium velkleur" + "mediumdonker velkleur" + "donker velkleur" + diff --git a/emojipicker/src/main/res/values-am/strings.xml b/emojipicker/src/main/res/values-am/strings.xml new file mode 100644 index 000000000..5be491cca --- /dev/null +++ b/emojipicker/src/main/res/values-am/strings.xml @@ -0,0 +1,42 @@ + + + + + "በቅርብ ጊዜ ጥቅም ላይ የዋለ" + "ሳቂታዎች እና ስሜቶች" + "ሰዎች" + "እንስሳት እና ተፈጥሮ" + "ምግብ እና መጠጥ" + "ጉዞ እና ቦታዎች" + "እንቅስቃሴዎች እና ክስተቶች" + "ነገሮች" + "ምልክቶች" + "ባንዲራዎች" + "ምንም ስሜት ገላጭ ምስሎች አይገኙም" + "ምንም ስሜት ገላጭ ምስሎችን እስካሁን አልተጠቀሙም" + "የስሜት ገላጭ ምስል ባለሁለት አቅጣጫ መቀያየሪያ" + "የስሜት ገላጭ ምስል አቅጣጫ ተቀይሯል" + "የስሜት ገላጭ ምስል ተለዋዋጭ መራጭ" + "%1$s እና %2$s" + "ጥላ" + "ነጣ ያለ የቆዳ ቀለም" + "መካከለኛ ነጣ ያለ የቆዳ ቀለም" + "መካከለኛ የቆዳ ቀለም" + "መካከለኛ ጠቆር ያለ የቆዳ ቀለም" + "ጠቆር ያለ የቆዳ ቀለም" + diff --git a/emojipicker/src/main/res/values-ar/strings.xml b/emojipicker/src/main/res/values-ar/strings.xml new file mode 100644 index 000000000..4d42ff9e9 --- /dev/null +++ b/emojipicker/src/main/res/values-ar/strings.xml @@ -0,0 +1,42 @@ + + + + + "المستخدمة حديثًا" + "الوجوه المبتسمة والرموز التعبيرية" + "الأشخاص" + "الحيوانات والطبيعة" + "المأكولات والمشروبات" + "السفر والأماكن" + "الأنشطة والأحداث" + "عناصر متنوعة" + "الرموز" + "الأعلام" + "لا تتوفر أي رموز تعبيرية." + "لم تستخدم أي رموز تعبيرية حتى الآن." + "مفتاح ثنائي الاتجاه للرموز التعبيرية" + "تم تغيير اتجاه الإيموجي" + "أداة اختيار الرموز التعبيرية" + "‏%1$s و%2$s" + "الظل" + "بشرة فاتحة" + "بشرة فاتحة متوسّطة" + "بشرة متوسّطة" + "بشرة داكنة متوسّطة" + "بشرة داكنة" + diff --git a/emojipicker/src/main/res/values-as/strings.xml b/emojipicker/src/main/res/values-as/strings.xml new file mode 100644 index 000000000..6ca5f5b7c --- /dev/null +++ b/emojipicker/src/main/res/values-as/strings.xml @@ -0,0 +1,42 @@ + + + + + "অলপতে ব্যৱহৃত" + "স্মাইলী আৰু আৱেগ" + "মানুহ" + "পশু আৰু প্ৰকৃতি" + "খাদ্য আৰু পানীয়" + "ভ্ৰমণ আৰু স্থান" + "কাৰ্যকলাপ আৰু অনুষ্ঠান" + "বস্তু" + "চিহ্ন" + "পতাকা" + "কোনো ইম’জি উপলব্ধ নহয়" + "আপুনি এতিয়ালৈকে কোনো ইম’জি ব্যৱহাৰ কৰা নাই" + "ইম’জি বাইডাইৰেকশ্বনেল ছুইচ্চাৰ" + "দিক্-নিৰ্দেশনা প্ৰদৰ্শন কৰা ইম’জি সলনি কৰা হৈছে" + "ইম’জিৰ প্ৰকাৰ বাছনি কৰোঁতা" + "%1$s আৰু %2$s" + "ছাঁ" + "পাতলীয়া ছালৰ ৰং" + "মধ্যমীয়া পাতল ছালৰ ৰং" + "মিঠাবৰণীয়া ছালৰ ৰং" + "মধ্যমীয়া গাঢ় ছালৰ ৰং" + "গাঢ় ছালৰ ৰং" + diff --git a/emojipicker/src/main/res/values-az/strings.xml b/emojipicker/src/main/res/values-az/strings.xml new file mode 100644 index 000000000..c4c528575 --- /dev/null +++ b/emojipicker/src/main/res/values-az/strings.xml @@ -0,0 +1,42 @@ + + + + + "SON İSTİFADƏ EDİLƏN" + "SMAYLİK VƏ EMOSİYALAR" + "ADAMLAR" + "HEYVANLAR VƏ TƏBİƏT" + "QİDA VƏ İÇKİ" + "SƏYAHƏT VƏ MƏKANLAR" + "FƏALİYYƏTLƏR VƏ TƏDBİRLƏR" + "OBYEKTLƏR" + "SİMVOLLAR" + "BAYRAQLAR" + "Əlçatan emoji yoxdur" + "Hələ heç bir emojidən istifadə etməməsiniz" + "ikitərəfli emoji dəyişdirici" + "emoji istiqaməti dəyişdirildi" + "emoji variant seçicisi" + "%1$s və %2$s" + "kölgə" + "açıq dəri rəngi" + "orta açıq dəri rəngi" + "orta dəri rəngi" + "orta tünd dəri rəngi" + "tünd dəri rəngi" + diff --git a/emojipicker/src/main/res/values-b+sr+Latn/strings.xml b/emojipicker/src/main/res/values-b+sr+Latn/strings.xml new file mode 100644 index 000000000..8feb29612 --- /dev/null +++ b/emojipicker/src/main/res/values-b+sr+Latn/strings.xml @@ -0,0 +1,42 @@ + + + + + "NEDAVNO KORIŠĆENO" + "SMAJLIJI I EMOCIJE" + "LJUDI" + "ŽIVOTINJE I PRIRODA" + "HRANA I PIĆE" + "PUTOVANJA I MESTA" + "AKTIVNOSTI I DOGAĐAJI" + "OBJEKTI" + "SIMBOLI" + "ZASTAVE" + "Emodžiji nisu dostupni" + "Još niste koristili emodžije" + "dvosmerni prebacivač emodžija" + "smer emodžija je promenjen" + "birač varijanti emodžija" + "%1$s i %2$s" + "senka" + "koža svetle puti" + "koža srednjesvetle puti" + "koža srednje puti" + "koža srednjetamne puti" + "koža tamne puti" + diff --git a/emojipicker/src/main/res/values-be/strings.xml b/emojipicker/src/main/res/values-be/strings.xml new file mode 100644 index 000000000..67dc3c2e6 --- /dev/null +++ b/emojipicker/src/main/res/values-be/strings.xml @@ -0,0 +1,42 @@ + + + + + "НЯДАЎНА ВЫКАРЫСТАНЫЯ" + "СМАЙЛІКІ І ЭМОЦЫІ" + "ЛЮДЗІ" + "ЖЫВЁЛЫ І ПРЫРОДА" + "ЕЖА І НАПОІ" + "ПАДАРОЖЖЫ І МЕСЦЫ" + "ДЗЕЯННІ І ПАДЗЕІ" + "АБ\'ЕКТЫ" + "СІМВАЛЫ" + "СЦЯГІ" + "Няма даступных эмодзі" + "Вы пакуль не выкарыстоўвалі эмодзі" + "пераключальнік кірунку для эмодзі" + "кірунак арыентацыі эмодзі зменены" + "інструмент выбару варыянтаў эмодзі" + "%1$s і %2$s" + "цень" + "светлы колер скуры" + "умерана светлы колер скуры" + "нейтральны колер скуры" + "умерана цёмны колер скуры" + "цёмны колер скуры" + diff --git a/emojipicker/src/main/res/values-bg/strings.xml b/emojipicker/src/main/res/values-bg/strings.xml new file mode 100644 index 000000000..929d7676e --- /dev/null +++ b/emojipicker/src/main/res/values-bg/strings.xml @@ -0,0 +1,42 @@ + + + + + "НАСКОРО ИЗПОЛЗВАНИ" + "ЕМОТИКОНИ И ЕМОЦИИ" + "ХОРА" + "ЖИВОТНИ И ПРИРОДА" + "ХРАНИ И НАПИТКИ" + "ПЪТУВАНИЯ И МЕСТА" + "АКТИВНОСТИ И СЪБИТИЯ" + "ПРЕДМЕТИ" + "СИМВОЛИ" + "ЗНАМЕНА" + "Няма налични емоджи" + "Все още не сте използвали емоджита" + "двупосочен превключвател на емоджи" + "посоката на емоджи бе променена" + "инструмент за избор на варианти за емоджи" + "%1$s и %2$s" + "сянка" + "светъл цвят на кожата" + "средно светъл цвят на кожата" + "междинен цвят на кожата" + "средно тъмен цвят на кожата" + "тъмен цвят на кожата" + diff --git a/emojipicker/src/main/res/values-bn/strings.xml b/emojipicker/src/main/res/values-bn/strings.xml new file mode 100644 index 000000000..55a691f28 --- /dev/null +++ b/emojipicker/src/main/res/values-bn/strings.xml @@ -0,0 +1,42 @@ + + + + + "সম্প্রতি ব্যবহার করা হয়েছে" + "স্মাইলি ও আবেগ" + "ব্যক্তি" + "প্রাণী ও প্রকৃতি" + "খাদ্য ও পানীয়" + "ভ্রমণ ও জায়গা" + "অ্যাক্টিভিটি ও ইভেন্ট" + "অবজেক্ট" + "প্রতীক" + "ফ্ল্যাগ" + "কোনও ইমোজি উপলভ্য নেই" + "আপনি এখনও কোনও ইমোজি ব্যবহার করেননি" + "ইমোজি দ্বিমুখী সুইচার" + "ইমোজির দিক পরিবর্তন হয়েছে" + "ইমোজি ভেরিয়েন্ট বাছাইকারী" + "%1$s এবং %2$s" + "ছায়া" + "হাল্কা স্কিন টোন" + "মাঝারি-হাল্কা স্কিন টোন" + "মাঝারি স্কিন টোন" + "মাঝারি-গাঢ় স্কিন টোন" + "গাঢ় স্কিন টোন" + diff --git a/emojipicker/src/main/res/values-bs/strings.xml b/emojipicker/src/main/res/values-bs/strings.xml new file mode 100644 index 000000000..401f6c827 --- /dev/null +++ b/emojipicker/src/main/res/values-bs/strings.xml @@ -0,0 +1,42 @@ + + + + + "NEDAVNO KORIŠTENO" + "SMAJLIJI I EMOCIJE" + "OSOBE" + "ŽIVOTINJE I PRIRODA" + "HRANA I PIĆE" + "PUTOVANJA I MJESTA" + "AKTIVNOSTI I DOGAĐAJI" + "PREDMETI" + "SIMBOLI" + "ZASTAVE" + "Emoji sličice nisu dostupne" + "Još niste koristili nijednu emoji sličicu" + "dvosmjerni prebacivač emodžija" + "emodži gleda u smjeru postavke prekidača" + "birač varijanti emodžija" + "%1$s i %2$s" + "sjenka" + "svijetla boja kože" + "srednje svijetla boja kože" + "srednja boja kože" + "srednje tamna boja kože" + "tamna boja kože" + diff --git a/emojipicker/src/main/res/values-ca/strings.xml b/emojipicker/src/main/res/values-ca/strings.xml new file mode 100644 index 000000000..09e2bc9a8 --- /dev/null +++ b/emojipicker/src/main/res/values-ca/strings.xml @@ -0,0 +1,42 @@ + + + + + "UTILITZATS FA POC" + "EMOTICONES I EMOCIONS" + "PERSONES" + "ANIMALS I NATURALESA" + "MENJAR I BEGUDA" + "VIATGES I LLOCS" + "ACTIVITATS I ESDEVENIMENTS" + "OBJECTES" + "SÍMBOLS" + "BANDERES" + "No hi ha cap emoji disponible" + "Encara no has fet servir cap emoji" + "selector bidireccional d\'emojis" + "s\'ha canviat la direcció de l\'emoji" + "selector de variants d\'emojis" + "%1$s i %2$s" + "ombra" + "to de pell clar" + "to de pell mitjà-clar" + "to de pell mitjà" + "to de pell mitjà-fosc" + "to de pell fosc" + diff --git a/emojipicker/src/main/res/values-cs/strings.xml b/emojipicker/src/main/res/values-cs/strings.xml new file mode 100644 index 000000000..8d7e0f502 --- /dev/null +++ b/emojipicker/src/main/res/values-cs/strings.xml @@ -0,0 +1,42 @@ + + + + + "NEDÁVNO POUŽITÉ" + "SMAJLÍCI A EMOCE" + "LIDÉ" + "ZVÍŘATA A PŘÍRODA" + "JÍDLO A PITÍ" + "CESTOVÁNÍ A MÍSTA" + "AKTIVITY A UDÁLOSTI" + "OBJEKTY" + "SYMBOLY" + "VLAJKY" + "Nejsou k dispozici žádné smajlíky" + "Zatím jste žádná emodži nepoužili" + "dvousměrný přepínač smajlíků" + "směr pohledu smajlíků přepnut" + "výběr variant emodži" + "%1$s a %2$s" + "stín" + "světlý tón pleti" + "středně světlý tón pleti" + "střední tón pleti" + "středně tmavý tón pleti" + "tmavý tón pleti" + diff --git a/emojipicker/src/main/res/values-da/strings.xml b/emojipicker/src/main/res/values-da/strings.xml new file mode 100644 index 000000000..e9eb67b95 --- /dev/null +++ b/emojipicker/src/main/res/values-da/strings.xml @@ -0,0 +1,42 @@ + + + + + "BRUGT FOR NYLIG" + "SMILEYS OG HUMØRIKONER" + "PERSONER" + "DYR OG NATUR" + "MAD OG DRIKKE" + "REJSER OG STEDER" + "AKTIVITETER OG BEGIVENHEDER" + "TING" + "SYMBOLER" + "FLAG" + "Der er ingen tilgængelige emojis" + "Du har ikke brugt nogen emojis endnu" + "tovejsskifter til emojis" + "emojien vender en anden retning" + "vælger for emojivariant" + "%1$s og %2$s" + "skygge" + "lys hudfarve" + "mellemlys hudfarve" + "medium hudfarve" + "mellemmørk hudfarve" + "mørk hudfarve" + diff --git a/emojipicker/src/main/res/values-de/strings.xml b/emojipicker/src/main/res/values-de/strings.xml new file mode 100644 index 000000000..6e72ab753 --- /dev/null +++ b/emojipicker/src/main/res/values-de/strings.xml @@ -0,0 +1,42 @@ + + + + + "ZULETZT VERWENDET" + "SMILEYS UND EMOTIONEN" + "PERSONEN" + "TIERE UND NATUR" + "ESSEN UND TRINKEN" + "REISEN UND ORTE" + "AKTIVITÄTEN UND EVENTS" + "OBJEKTE" + "SYMBOLE" + "FLAGGEN" + "Keine Emojis verfügbar" + "Du hast noch keine Emojis verwendet" + "Bidirektionale Emoji-Auswahl" + "Emoji-Richtung geändert" + "Emojivarianten-Auswahl" + "%1$s und %2$s" + "Hautton" + "Heller Hautton" + "Mittelheller Hautton" + "Mittlerer Hautton" + "Mitteldunkler Hautton" + "Dunkler Hautton" + diff --git a/emojipicker/src/main/res/values-el/strings.xml b/emojipicker/src/main/res/values-el/strings.xml new file mode 100644 index 000000000..4a59ed678 --- /dev/null +++ b/emojipicker/src/main/res/values-el/strings.xml @@ -0,0 +1,42 @@ + + + + + "ΧΡΗΣΙΜΟΠΟΙΗΘΗΚΑΝ ΠΡΟΣΦΑΤΑ" + "ΕΙΚΟΝΙΔΙΑ SMILEY ΚΑΙ ΣΥΝΑΙΣΘΗΜΑΤΑ" + "ΑΤΟΜΑ" + "ΖΩΑ ΚΑΙ ΦΥΣΗ" + "ΦΑΓΗΤΟ ΚΑΙ ΠΟΤΟ" + "ΤΑΞΙΔΙΑ ΚΑΙ ΜΕΡΗ" + "ΔΡΑΣΤΗΡΙΟΤΗΤΕΣ ΚΑΙ ΣΥΜΒΑΝΤΑ" + "ΑΝΤΙΚΕΙΜΕΝΑ" + "ΣΥΜΒΟΛΑ" + "ΣΗΜΑΙΕΣ" + "Δεν υπάρχουν διαθέσιμα emoji" + "Δεν έχετε χρησιμοποιήσει κανένα emoji ακόμα" + "αμφίδρομο στοιχείο εναλλαγής emoji" + "έγινε εναλλαγή της κατεύθυνσης που είναι στραμμένο το emoji" + "επιλογέας παραλλαγής emoji" + "%1$s και %2$s" + "σκιά" + "ανοιχτός τόνος επιδερμίδας" + "μεσαίος προς ανοιχτός τόνος επιδερμίδας" + "μεσαίος τόνος επιδερμίδας" + "μεσαίος προς σκούρος τόνος επιδερμίδας" + "σκούρος τόνος επιδερμίδας" + diff --git a/emojipicker/src/main/res/values-en-rAU/strings.xml b/emojipicker/src/main/res/values-en-rAU/strings.xml new file mode 100644 index 000000000..0b651f515 --- /dev/null +++ b/emojipicker/src/main/res/values-en-rAU/strings.xml @@ -0,0 +1,42 @@ + + + + + "RECENTLY USED" + "SMILEYS AND EMOTIONS" + "PEOPLE" + "ANIMALS AND NATURE" + "FOOD AND DRINK" + "TRAVEL AND PLACES" + "ACTIVITIES AND EVENTS" + "OBJECTS" + "SYMBOLS" + "FLAGS" + "No emojis available" + "You haven\'t used any emoji yet" + "emoji bidirectional switcher" + "emoji facing direction switched" + "emoji variant selector" + "%1$s and %2$s" + "shadow" + "light skin tone" + "medium-light skin tone" + "medium skin tone" + "medium-dark skin tone" + "dark skin tone" + diff --git a/emojipicker/src/main/res/values-en-rCA/strings.xml b/emojipicker/src/main/res/values-en-rCA/strings.xml new file mode 100644 index 000000000..d056590cc --- /dev/null +++ b/emojipicker/src/main/res/values-en-rCA/strings.xml @@ -0,0 +1,42 @@ + + + + + "RECENTLY USED" + "SMILEYS AND EMOTIONS" + "PEOPLE" + "ANIMALS AND NATURE" + "FOOD AND DRINK" + "TRAVEL AND PLACES" + "ACTIVITIES AND EVENTS" + "OBJECTS" + "SYMBOLS" + "FLAGS" + "No emojis available" + "You haven\'t used any emojis yet" + "emoji bidirectional switcher" + "emoji facing direction switched" + "emoji variant selector" + "%1$s and %2$s" + "shadow" + "light skin tone" + "medium light skin tone" + "medium skin tone" + "medium dark skin tone" + "dark skin tone" + diff --git a/emojipicker/src/main/res/values-en-rGB/strings.xml b/emojipicker/src/main/res/values-en-rGB/strings.xml new file mode 100644 index 000000000..0b651f515 --- /dev/null +++ b/emojipicker/src/main/res/values-en-rGB/strings.xml @@ -0,0 +1,42 @@ + + + + + "RECENTLY USED" + "SMILEYS AND EMOTIONS" + "PEOPLE" + "ANIMALS AND NATURE" + "FOOD AND DRINK" + "TRAVEL AND PLACES" + "ACTIVITIES AND EVENTS" + "OBJECTS" + "SYMBOLS" + "FLAGS" + "No emojis available" + "You haven\'t used any emoji yet" + "emoji bidirectional switcher" + "emoji facing direction switched" + "emoji variant selector" + "%1$s and %2$s" + "shadow" + "light skin tone" + "medium-light skin tone" + "medium skin tone" + "medium-dark skin tone" + "dark skin tone" + diff --git a/emojipicker/src/main/res/values-en-rIN/strings.xml b/emojipicker/src/main/res/values-en-rIN/strings.xml new file mode 100644 index 000000000..0b651f515 --- /dev/null +++ b/emojipicker/src/main/res/values-en-rIN/strings.xml @@ -0,0 +1,42 @@ + + + + + "RECENTLY USED" + "SMILEYS AND EMOTIONS" + "PEOPLE" + "ANIMALS AND NATURE" + "FOOD AND DRINK" + "TRAVEL AND PLACES" + "ACTIVITIES AND EVENTS" + "OBJECTS" + "SYMBOLS" + "FLAGS" + "No emojis available" + "You haven\'t used any emoji yet" + "emoji bidirectional switcher" + "emoji facing direction switched" + "emoji variant selector" + "%1$s and %2$s" + "shadow" + "light skin tone" + "medium-light skin tone" + "medium skin tone" + "medium-dark skin tone" + "dark skin tone" + diff --git a/emojipicker/src/main/res/values-en-rXC/strings.xml b/emojipicker/src/main/res/values-en-rXC/strings.xml new file mode 100644 index 000000000..3e02185f4 --- /dev/null +++ b/emojipicker/src/main/res/values-en-rXC/strings.xml @@ -0,0 +1,42 @@ + + + + + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‏‏‏‏‎‏‏‎‏‎‎‎‏‏‎‏‎‏‎‏‏‏‏‏‎‏‏‎‏‏‎‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎‎‏‎‎‏‏‏‎RECENTLY USED‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‏‏‎‎‏‎‏‏‎‏‏‎‎‏‏‏‎‎‎‏‏‏‎‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‎‏‎‎‏‏‏‎‎‎‎‎‏‎SMILEYS AND EMOTIONS‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‎‏‎‎‏‎‏‎‎‎‏‏‎‏‏‏‎‏‎‏‏‎‏‏‏‏‏‎‎‎‏‏‎‏‎‏‎‏‏‏‏‎‏‎‏‎‏‏‎‎‎‏‎PEOPLE‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‎‎‏‏‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‏‎‏‎‎‏‏‏‎‎‏‎‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‎‎‏‎‏‎‏‎ANIMALS AND NATURE‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‎‎‎‎‏‎‎‎‏‏‎‎‏‎‏‎‏‎‏‎‎‏‎‎‏‎‏‎‎‏‏‏‏‎‎‎‎‏‏‏‎‏‎‏‏‎FOOD AND DRINK‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‏‏‎‏‎‎‏‎‎‏‎‎‎‏‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‎‎‎‏‏‎‎‎‎‎‎‎TRAVEL AND PLACES‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‏‎‎‏‏‏‎‏‎‏‏‎‎‏‎‏‏‎‎‏‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‎ACTIVITIES AND EVENTS‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‏‎‏‎‎‎‏‏‏‏‏‎‎‎‏‏‎‎‎‏‏‎‎‎‎‏‏‎‏‎‏‏‎‎‏‎‎‏‏‎‎‏‏‏‎‎‎‏‏‎OBJECTS‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‏‎‏‎‎‎‎‏‎‏‏‎‏‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‏‏‏‎‎‎‎‏‏‎‎‎‎‎‎‎‏‏‎‏‏‎SYMBOLS‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‎‏‏‏‏‏‎‎‏‏‏‎‎‏‎‏‏‎‏‏‎‎‎‎‎‏‎‎‏‎‏‏‎‎‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‏‎FLAGS‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‎‏‎‎‎‎‏‏‎‏‎‏‏‎‏‎‏‏‎‎‎‎‎‎‎‏‎‏‎‏‎‎‏‏‎‎‎‎‎‏‎‏‎‎‏‎‏‎‎‎‏‎No emojis available‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‎‎‎‏‎‎‎‎‏‏‎‏‏‎‎‏‏‏‎‎‎‎‏‎‎‎‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎‎‏‎‏‎‏‎‏‏‎‎‎‎You haven\'t used any emojis yet‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‏‎‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‎‎‏‏‏‏‎‏‎‏‏‏‎‏‎‎‏‎‏‎‎‎‎‏‎‏‎‎‎‏‏‏‏‎‏‎emoji bidirectional switcher‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‏‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‎‎‎‎‎‏‏‎emoji facing direction switched‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‎‏‏‏‏‎‏‎‏‎‏‏‎‏‎‎‎‏‎‎‏‎‎‏‎‎‎‏‏‎‏‎‏‎‎‏‏‎‎‎‎‎‎emoji variant selector‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‏‎‎‎‏‎‎‏‎‏‏‏‎‎‏‎‎‏‎‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‎‏‎‏‎‎‎‏‎‏‏‏‏‎‏‎‎‎‏‎%1$s and %2$s‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‏‏‎‏‏‎‎‎‏‏‏‎‎‎‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‏‎‏‎‎‏‏‏‏‎‎‎‎‏‏‏‎‏‎‏‏‎‎‎‎‎shadow‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‏‎‏‎‎‏‎‎‏‏‎‏‏‏‎‏‎‏‎‏‎‎‏‎‏‏‎‏‎‎‎‎‎‏‎‎‏‏‎‎‎‏‏‏‏‎‎‏‎‎‎‏‎light skin tone‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‏‎‎‏‎‎‏‏‏‎‎‎‎‎‏‏‏‏‏‏‎‎‏‏‎‏‏‎‎‎‎‎‏‏‎‎‏‎‏‎‏‏‎‏‏‎‏‏‎‏‎‏‎‎medium light skin tone‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‏‏‎‏‏‎‏‎‎‏‎‏‏‏‏‎‏‎‎‎‎‎‎‏‎‏‎‏‏‎‎‏‏‎‏‏‏‎‎‎‏‎‎‎‎‎‏‏‎medium skin tone‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‏‎‏‎‏‎‎‏‏‏‎‎‏‎‎‎‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‏‏‏‎‎‎‏‎‏‏‏‏‎‏‎‏‎‏‎‏‏‎‏‎medium dark skin tone‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‏‎‎‏‎‏‎‏‎‎‎‎‏‎‏‎‏‏‎‎‎‎‏‎‎‎‏‏‎‎‎‎‎‎‏‏‏‎‎‏‏‎‎‏‏‏‏‎‏‏‏‎‎dark skin tone‎‏‎‎‏‎" + diff --git a/emojipicker/src/main/res/values-es-rUS/strings.xml b/emojipicker/src/main/res/values-es-rUS/strings.xml new file mode 100644 index 000000000..e9001edfe --- /dev/null +++ b/emojipicker/src/main/res/values-es-rUS/strings.xml @@ -0,0 +1,42 @@ + + + + + "USADOS RECIENTEMENTE" + "EMOTICONES Y EMOCIONES" + "PERSONAS" + "ANIMALES Y NATURALEZA" + "COMIDAS Y BEBIDAS" + "VIAJES Y LUGARES" + "ACTIVIDADES Y EVENTOS" + "OBJETOS" + "SÍMBOLOS" + "BANDERAS" + "No hay ningún emoji disponible" + "Todavía no usaste ningún emoji" + "selector bidireccional de emojis" + "se cambió la dirección del emoji" + "selector de variantes de emojis" + "%1$s y %2$s" + "sombra" + "tono de piel claro" + "tono de piel medio claro" + "tono de piel intermedio" + "tono de piel medio oscuro" + "tono de piel oscuro" + diff --git a/emojipicker/src/main/res/values-es/strings.xml b/emojipicker/src/main/res/values-es/strings.xml new file mode 100644 index 000000000..d2aed3688 --- /dev/null +++ b/emojipicker/src/main/res/values-es/strings.xml @@ -0,0 +1,42 @@ + + + + + "USADOS RECIENTEMENTE" + "EMOTICONOS Y EMOCIONES" + "PERSONAS" + "ANIMALES Y NATURALEZA" + "COMIDA Y BEBIDA" + "VIAJES Y SITIOS" + "ACTIVIDADES Y EVENTOS" + "OBJETOS" + "SÍMBOLOS" + "BANDERAS" + "No hay emojis disponibles" + "Aún no has usado ningún emoji" + "cambio bidireccional de emojis" + "dirección a la que se orienta el emoji cambiada" + "selector de variantes de emojis" + "%1$s y %2$s" + "sombra" + "tono de piel claro" + "tono de piel medio claro" + "tono de piel medio" + "tono de piel medio oscuro" + "tono de piel oscuro" + diff --git a/emojipicker/src/main/res/values-et/strings.xml b/emojipicker/src/main/res/values-et/strings.xml new file mode 100644 index 000000000..8b3d05aa9 --- /dev/null +++ b/emojipicker/src/main/res/values-et/strings.xml @@ -0,0 +1,42 @@ + + + + + "HILJUTI KASUTATUD" + "NÄOIKOONID JA EMOTSIOONID" + "INIMESED" + "LOOMAD JA LOODUS" + "SÖÖK JA JOOK" + "REISIMINE JA KOHAD" + "TEGEVUSED JA SÜNDMUSED" + "OBJEKTID" + "SÜMBOLID" + "LIPUD" + "Ühtegi emotikoni pole saadaval" + "Te pole veel ühtegi emotikoni kasutanud" + "emotikoni kahesuunaline lüliti" + "emotikoni suunda vahetati" + "emotikoni variandi valija" + "%1$s ja %2$s" + "vari" + "hele nahatoon" + "keskmiselt hele nahatoon" + "keskmine nahatoon" + "keskmiselt tume nahatoon" + "tume nahatoon" + diff --git a/emojipicker/src/main/res/values-eu/strings.xml b/emojipicker/src/main/res/values-eu/strings.xml new file mode 100644 index 000000000..9c550ca96 --- /dev/null +++ b/emojipicker/src/main/res/values-eu/strings.xml @@ -0,0 +1,42 @@ + + + + + "ERABILITAKO AZKENAK" + "AURPEGIERAK ETA ALDARTEAK" + "JENDEA" + "ANIMALIAK ETA NATURA" + "JAN-EDANAK" + "BIDAIAK ETA TOKIAK" + "JARDUERAK ETA GERTAERAK" + "OBJEKTUAK" + "IKURRAK" + "BANDERAK" + "Ez dago emotikonorik erabilgarri" + "Ez duzu erabili emojirik oraingoz" + "noranzko biko emoji-aldatzailea" + "emojiaren norabidea aldatu da" + "emojien aldaeren hautatzailea" + "%1$s eta %2$s" + "itzala" + "azalaren tonu argia" + "azalaren tonu argixka" + "azalaren tarteko tonua" + "azalaren tonu ilunxkoa" + "azalaren tonu iluna" + diff --git a/emojipicker/src/main/res/values-fa/strings.xml b/emojipicker/src/main/res/values-fa/strings.xml new file mode 100644 index 000000000..5930a4f02 --- /dev/null +++ b/emojipicker/src/main/res/values-fa/strings.xml @@ -0,0 +1,42 @@ + + + + + "اخیراً استفاده‌شده" + "شکلک‌ها و احساسات" + "افراد" + "حیوانات و طبیعت" + "غذا و نوشیدنی" + "سفر و مکان‌ها" + "فعالیت‌ها و رویدادها" + "اشیاء" + "نشان‌ها" + "پرچم‌ها" + "اموجی دردسترس نیست" + "هنوز از هیچ اموجی‌ای استفاده نکرده‌اید" + "تغییردهنده دوسویه اموجی" + "جهت چهره اموجی تغییر کرد" + "گزینشگر متغیر اموجی" + "‏%1$s و %2$s" + "سایه" + "رنگ‌مایه پوست روشن" + "رنگ‌مایه پوست ملایم روشن" + "رنگ‌مایه پوست ملایم" + "رنگ‌مایه پوست ملایم تیره" + "رنگ‌مایه پوست تیره" + diff --git a/emojipicker/src/main/res/values-fi/strings.xml b/emojipicker/src/main/res/values-fi/strings.xml new file mode 100644 index 000000000..bb6ccb586 --- /dev/null +++ b/emojipicker/src/main/res/values-fi/strings.xml @@ -0,0 +1,42 @@ + + + + + "VIIMEKSI KÄYTETYT" + "HYMIÖT JA TUNNETILAT" + "IHMISET" + "ELÄIMET JA LUONTO" + "RUOKA JA JUOMA" + "MATKAILU JA PAIKAT" + "AKTIVITEETIT JA TAPAHTUMAT" + "ESINEET" + "SYMBOLIT" + "LIPUT" + "Ei emojeita saatavilla" + "Et ole vielä käyttänyt emojeita" + "emoji kaksisuuntainen vaihtaja" + "emojin osoitussuunta vaihdettu" + "emojivalitsin" + "%1$s ja %2$s" + "varjostus" + "vaalea ihonväri" + "melko vaalea ihonväri" + "keskimääräinen ihonväri" + "melko tumma ihonväri" + "tumma ihonväri" + diff --git a/emojipicker/src/main/res/values-fr-rCA/strings.xml b/emojipicker/src/main/res/values-fr-rCA/strings.xml new file mode 100644 index 000000000..334f18f51 --- /dev/null +++ b/emojipicker/src/main/res/values-fr-rCA/strings.xml @@ -0,0 +1,42 @@ + + + + + "UTILISÉS RÉCEMMENT" + "ÉMOTICÔNES ET ÉMOTIONS" + "PERSONNES" + "ANIMAUX ET NATURE" + "ALIMENTS ET BOISSONS" + "VOYAGES ET LIEUX" + "ACTIVITÉS ET ÉVÉNEMENTS" + "OBJETS" + "SYMBOLES" + "DRAPEAUX" + "Aucun émoji proposé" + "Vous n\'avez encore utilisé aucun émoji" + "sélecteur bidirectionnel d\'émoji" + "Émoji tourné dans la direction inverse" + "sélecteur de variantes d\'émoji" + "%1$s et %2$s" + "ombre" + "teint clair" + "teint moyennement clair" + "teint moyen" + "teint moyennement foncé" + "teint foncé" + diff --git a/emojipicker/src/main/res/values-fr/strings.xml b/emojipicker/src/main/res/values-fr/strings.xml new file mode 100644 index 000000000..66f9f4d88 --- /dev/null +++ b/emojipicker/src/main/res/values-fr/strings.xml @@ -0,0 +1,42 @@ + + + + + "UTILISÉS RÉCEMMENT" + "ÉMOTICÔNES ET ÉMOTIONS" + "PERSONNES" + "ANIMAUX ET NATURE" + "ALIMENTATION ET BOISSONS" + "VOYAGES ET LIEUX" + "ACTIVITÉS ET ÉVÉNEMENTS" + "OBJETS" + "SYMBOLES" + "DRAPEAUX" + "Aucun emoji disponible" + "Vous n\'avez pas encore utilisé d\'emoji" + "sélecteur d\'emoji bidirectionnel" + "sens de l\'orientation de l\'emoji inversé" + "sélecteur de variante d\'emoji" + "%1$s et %2$s" + "ombre" + "teint clair" + "teint intermédiaire à clair" + "teint intermédiaire" + "teint intermédiaire à foncé" + "teint foncé" + diff --git a/emojipicker/src/main/res/values-gl/strings.xml b/emojipicker/src/main/res/values-gl/strings.xml new file mode 100644 index 000000000..f8715c36d --- /dev/null +++ b/emojipicker/src/main/res/values-gl/strings.xml @@ -0,0 +1,42 @@ + + + + + "USADOS HAI POUCO" + "ICONAS XESTUAIS E EMOTICONAS" + "PERSOAS" + "ANIMAIS E NATUREZA" + "COMIDA E BEBIDA" + "VIAXES E LUGARES" + "ACTIVIDADES E EVENTOS" + "OBXECTOS" + "SÍMBOLOS" + "BANDEIRAS" + "Non hai ningún emoji dispoñible" + "Aínda non utilizaches ningún emoji" + "selector bidireccional de emojis" + "dirección do emoji cambiada" + "selector de variantes de emojis" + "%1$s e %2$s" + "sombra" + "ton de pel claro" + "ton de pel lixeiramente claro" + "ton de pel medio" + "ton de pel lixeiramente escuro" + "ton de pel escuro" + diff --git a/emojipicker/src/main/res/values-gu/strings.xml b/emojipicker/src/main/res/values-gu/strings.xml new file mode 100644 index 000000000..dad9fd387 --- /dev/null +++ b/emojipicker/src/main/res/values-gu/strings.xml @@ -0,0 +1,42 @@ + + + + + "તાજેતરમાં વપરાયેલું" + "સ્માઇલી અને મનોભાવો" + "લોકો" + "પ્રાણીઓ અને પ્રકૃતિ" + "ભોજન અને પીણાં" + "મુસાફરી અને સ્થળો" + "પ્રવૃત્તિઓ અને ઇવેન્ટ" + "ઑબ્જેક્ટ" + "પ્રતીકો" + "ઝંડા" + "કોઈ ઇમોજી ઉપલબ્ધ નથી" + "તમે હજી સુધી કોઈ ઇમોજીનો ઉપયોગ કર્યો નથી" + "બે દિશામાં સ્વિચ થઈ શકતું ઇમોજી સ્વિચર" + "ઇમોજીની દિશા બદલવામાં આવી" + "ઇમોજીનો પ્રકાર પસંદગીકર્તા" + "%1$s અને %2$s" + "શૅડો" + "ત્વચાનો હળવો ટોન" + "ત્વચાનો મધ્યમ હળવો ટોન" + "ત્વચાનો મધ્યમ ટોન" + "ત્વચાનો મધ્યમ ઘેરો ટોન" + "ત્વચાનો ઘેરો ટોન" + diff --git a/emojipicker/src/main/res/values-hi/strings.xml b/emojipicker/src/main/res/values-hi/strings.xml new file mode 100644 index 000000000..81cd653a3 --- /dev/null +++ b/emojipicker/src/main/res/values-hi/strings.xml @@ -0,0 +1,42 @@ + + + + + "हाल ही में इस्तेमाल किए गए" + "स्माइली और भावनाएं" + "लोग" + "जानवर और प्रकृति" + "खाने-पीने की चीज़ें" + "यात्रा और जगहें" + "गतिविधियां और इवेंट" + "ऑब्जेक्ट" + "सिंबल" + "झंडे" + "कोई इमोजी उपलब्ध नहीं है" + "आपने अब तक किसी भी इमोजी का इस्तेमाल नहीं किया है" + "दोनों तरफ़ ले जा सकने वाले स्विचर का इमोजी" + "इमोजी को फ़्लिप किया गया" + "इमोजी के वैरिएंट चुनने का टूल" + "%1$s और %2$s" + "शैडो" + "हल्के रंग की त्वचा" + "थोड़े हल्के रंग की त्वचा" + "सामान्य रंग की त्वचा" + "थोड़े गहरे रंग की त्वचा" + "गहरे रंग की त्वचा" + diff --git a/emojipicker/src/main/res/values-hr/strings.xml b/emojipicker/src/main/res/values-hr/strings.xml new file mode 100644 index 000000000..481b48673 --- /dev/null +++ b/emojipicker/src/main/res/values-hr/strings.xml @@ -0,0 +1,42 @@ + + + + + "NEDAVNO KORIŠTENO" + "SMAJLIĆI I EMOCIJE" + "OSOBE" + "ŽIVOTINJE I PRIRODA" + "HRANA I PIĆE" + "PUTOVANJA I MJESTA" + "AKTIVNOSTI I DOGAĐAJI" + "OBJEKTI" + "SIMBOLI" + "ZASTAVE" + "Nije dostupan nijedan emoji" + "Još niste upotrijebili emojije" + "dvosmjerni izmjenjivač emojija" + "promijenjen je smjer emojija" + "alat za odabir varijante emojija" + "%1$s i %2$s" + "sjena" + "svijetla boja kože" + "srednje svijetla boja kože" + "srednja boja kože" + "srednje tamna boja kože" + "tamna boja kože" + diff --git a/emojipicker/src/main/res/values-hu/strings.xml b/emojipicker/src/main/res/values-hu/strings.xml new file mode 100644 index 000000000..d048746c7 --- /dev/null +++ b/emojipicker/src/main/res/values-hu/strings.xml @@ -0,0 +1,42 @@ + + + + + "LEGUTÓBB HASZNÁLT" + "HANGULATJELEK ÉS HANGULATOK" + "SZEMÉLYEK" + "ÁLLATOK ÉS TERMÉSZET" + "ÉTEL ÉS ITAL" + "UTAZÁS ÉS HELYEK" + "TEVÉKENYSÉGEK ÉS ESEMÉNYEK" + "TÁRGYAK" + "SZIMBÓLUMOK" + "ZÁSZLÓK" + "Nincsenek rendelkezésre álló emojik" + "Még nem használt emojikat" + "kétirányú emojiváltó" + "módosítva lett, hogy merre nézzen az emoji" + "emojiváltozat-választó" + "%1$s és %2$s" + "árnyék" + "világos bőrtónus" + "közepesen világos bőrtónus" + "közepes bőrtónus" + "közepesen sötét bőrtónus" + "sötét bőrtónus" + diff --git a/emojipicker/src/main/res/values-hy/strings.xml b/emojipicker/src/main/res/values-hy/strings.xml new file mode 100644 index 000000000..be551decf --- /dev/null +++ b/emojipicker/src/main/res/values-hy/strings.xml @@ -0,0 +1,42 @@ + + + + + "ՎԵՐՋԵՐՍ ՕԳՏԱԳՈՐԾՎԱԾ" + "ԶՄԱՅԼԻԿՆԵՐ ԵՎ ՀՈՒԶԱՊԱՏԿԵՐԱԿՆԵՐ" + "ՄԱՐԴԻԿ" + "ԿԵՆԴԱՆԻՆԵՐ ԵՎ ԲՆՈՒԹՅՈՒՆ" + "ՍՆՈՒՆԴ ԵՎ ԽՄԻՉՔ" + "ՃԱՄՓՈՐԴՈՒԹՅՈՒՆ ԵՎ ՏԵՍԱՐԺԱՆ ՎԱՅՐԵՐ" + "ԺԱՄԱՆՑ ԵՎ ՄԻՋՈՑԱՌՈՒՄՆԵՐ" + "ԱՌԱՐԿԱՆԵՐ" + "ՆՇԱՆՆԵՐ" + "ԴՐՈՇՆԵՐ" + "Հասանելի էմոջիներ չկան" + "Դուք դեռ չեք օգտագործել էմոջիներ" + "էմոջիների երկկողմանի փոխանջատիչ" + "էմոջիի դեմքի ուղղությունը փոխվեց" + "էմոջիների տարբերակի ընտրիչ" + "%1$s և %2$s" + "ստվեր" + "մաշկի բաց երանգ" + "մաշկի չափավոր բաց երանգ" + "մաշկի չեզոք երանգ" + "մաշկի չափավոր մուգ երանգ" + "մաշկի մուգ երանգ" + diff --git a/emojipicker/src/main/res/values-in/strings.xml b/emojipicker/src/main/res/values-in/strings.xml new file mode 100644 index 000000000..09703b727 --- /dev/null +++ b/emojipicker/src/main/res/values-in/strings.xml @@ -0,0 +1,42 @@ + + + + + "TERAKHIR DIGUNAKAN" + "SMILEY DAN EMOTIKON" + "ORANG" + "HEWAN DAN ALAM" + "MAKANAN DAN MINUMAN" + "WISATA DAN TEMPAT" + "AKTIVITAS DAN ACARA" + "OBJEK" + "SIMBOL" + "BENDERA" + "Tidak ada emoji yang tersedia" + "Anda belum menggunakan emoji apa pun" + "pengalih dua arah emoji" + "arah hadap emoji dialihkan" + "pemilih varian emoji" + "%1$s dan %2$s" + "bayangan" + "warna kulit cerah" + "warna kulit kuning langsat" + "warna kulit sawo matang" + "warna kulit cokelat" + "warna kulit gelap" + diff --git a/emojipicker/src/main/res/values-is/strings.xml b/emojipicker/src/main/res/values-is/strings.xml new file mode 100644 index 000000000..691d3c623 --- /dev/null +++ b/emojipicker/src/main/res/values-is/strings.xml @@ -0,0 +1,42 @@ + + + + + "NOTAÐ NÝLEGA" + "BROSKARLAR OG TILFINNINGAR" + "FÓLK" + "DÝR OG NÁTTÚRA" + "MATUR OG DRYKKUR" + "FERÐALÖG OG STAÐIR" + "VIRKNI OG VIÐBURÐIR" + "HLUTIR" + "TÁKN" + "FÁNAR" + "Engin emoji-tákn í boði" + "Þú hefur ekki notað nein emoji enn" + "emoji-val í báðar áttir" + "Áttinni sem emoji snýr að hefur verið breytt" + "val emoji-afbrigðis" + "%1$s og %2$s" + "skuggi" + "ljós húðlitur" + "meðalljós húðlitur" + "húðlitur í meðallagi" + "meðaldökkur húðlitur" + "dökkur húðlitur" + diff --git a/emojipicker/src/main/res/values-it/strings.xml b/emojipicker/src/main/res/values-it/strings.xml new file mode 100644 index 000000000..6ff2bf9c2 --- /dev/null +++ b/emojipicker/src/main/res/values-it/strings.xml @@ -0,0 +1,42 @@ + + + + + "USATE DI RECENTE" + "SMILE ED EMOZIONI" + "PERSONE" + "ANIMALI E NATURA" + "CIBO E BEVANDE" + "VIAGGI E LUOGHI" + "ATTIVITÀ ED EVENTI" + "OGGETTI" + "SIMBOLI" + "BANDIERE" + "Nessuna emoji disponibile" + "Non hai ancora usato alcuna emoji" + "selettore bidirezionale di emoji" + "emoji sottosopra" + "selettore variante emoji" + "%1$s e %2$s" + "ombra" + "carnagione chiara" + "carnagione medio-chiara" + "carnagione media" + "carnagione medio-scura" + "carnagione scura" + diff --git a/emojipicker/src/main/res/values-iw/strings.xml b/emojipicker/src/main/res/values-iw/strings.xml new file mode 100644 index 000000000..7a8eae8a7 --- /dev/null +++ b/emojipicker/src/main/res/values-iw/strings.xml @@ -0,0 +1,42 @@ + + + + + "בשימוש לאחרונה" + "סמיילי ואמוטיקונים" + "אנשים" + "בעלי חיים וטבע" + "מזון ומשקאות" + "נסיעות ומקומות" + "פעילויות ואירועים" + "אובייקטים" + "סמלים" + "דגלים" + "אין סמלי אמוג\'י זמינים" + "עדיין לא השתמשת באף אמוג\'י" + "לחצן דו-כיווני למעבר לאמוג\'י" + "מתג נגישות להחלפת הכיוון של האמוג\'י" + "בורר של סוגי אמוג\'י" + "‏%1$s ו-%2$s" + "צל" + "גוון עור בהיר" + "גוון עור בינוני-בהיר" + "גוון עור בינוני" + "גוון עור בינוני-כהה" + "גוון עור כהה" + diff --git a/emojipicker/src/main/res/values-ja/strings.xml b/emojipicker/src/main/res/values-ja/strings.xml new file mode 100644 index 000000000..395ee6d73 --- /dev/null +++ b/emojipicker/src/main/res/values-ja/strings.xml @@ -0,0 +1,42 @@ + + + + + "最近使用した絵文字" + "顔文字、気分" + "人物" + "動物、自然" + "食べ物、飲み物" + "移動、場所" + "活動、イベント" + "アイテム" + "記号" + "旗" + "使用できる絵文字がありません" + "まだ絵文字を使用していません" + "絵文字の双方向切り替え" + "絵文字の向きを切り替えました" + "絵文字バリエーション セレクタ" + "%1$s、%2$s" + "シャドウ" + "明るい肌の色" + "やや明るい肌の色" + "中間の明るさの肌の色" + "やや濃い肌の色" + "濃い肌の色" + diff --git a/emojipicker/src/main/res/values-ka/strings.xml b/emojipicker/src/main/res/values-ka/strings.xml new file mode 100644 index 000000000..5d23faa22 --- /dev/null +++ b/emojipicker/src/main/res/values-ka/strings.xml @@ -0,0 +1,42 @@ + + + + + "ბოლო დროს გამოყენებული" + "სიცილაკები და ემოციები" + "ადამიანები" + "ცხოველები და ბუნება" + "საჭმელი და სასმელი" + "მოგზაურობა და ადგილები" + "აქტივობები და მოვლენები" + "ობიექტები" + "სიმბოლოები" + "დროშები" + "Emoji-ები მიუწვდომელია" + "Emoji-ებით ჯერ არ გისარგებლიათ" + "emoji-ს ორმიმართულებიანი გადამრთველი" + "emoji-ის მიმართულება შეცვლილია" + "emoji-ს ვარიანტის ამომრჩევი" + "%1$s და %2$s" + "ჩრდილი" + "კანის ღია ტონი" + "კანის ღია საშუალო ტონი" + "კანის საშუალო ტონი" + "კანის მუქი საშუალო ტონი" + "კანის მუქი ტონი" + diff --git a/emojipicker/src/main/res/values-kk/strings.xml b/emojipicker/src/main/res/values-kk/strings.xml new file mode 100644 index 000000000..cd6a8c571 --- /dev/null +++ b/emojipicker/src/main/res/values-kk/strings.xml @@ -0,0 +1,42 @@ + + + + + "СОҢҒЫ ҚОЛДАНЫЛҒАНДАР" + "СМАЙЛДАР МЕН ЭМОЦИЯЛАР" + "АДАМДАР" + "ЖАНУАРЛАР ЖӘНЕ ТАБИҒАТ" + "ТАМАҚ ПЕН СУСЫН" + "САЯХАТ ЖӘНЕ ОРЫНДАР" + "ӘРЕКЕТТЕР МЕН ІС-ШАРАЛАР" + "НЫСАНДАР" + "ТАҢБАЛАР" + "ЖАЛАУШАЛАР" + "Эмоджи жоқ" + "Әлі ешқандай эмоджи пайдаланылған жоқ." + "екіжақты эмоджи ауыстырғыш" + "эмоджи бағыты ауыстырылды" + "эмоджи нұсқаларын таңдау құралы" + "%1$s және %2$s" + "көлеңке" + "терінің ақшыл реңі" + "терінің орташа ақшыл реңі" + "терінің орташа реңі" + "терінің орташа қараторы реңі" + "терінің қараторы реңі" + diff --git a/emojipicker/src/main/res/values-km/strings.xml b/emojipicker/src/main/res/values-km/strings.xml new file mode 100644 index 000000000..0b4dffc20 --- /dev/null +++ b/emojipicker/src/main/res/values-km/strings.xml @@ -0,0 +1,42 @@ + + + + + "បាន​ប្រើ​ថ្មីៗ​នេះ" + "រូប​ទឹក​មុខ និងអារម្មណ៍" + "មនុស្ស" + "សត្វ និងធម្មជាតិ" + "អាហារ និងភេសជ្ជៈ" + "ការធ្វើដំណើរ និងទីកន្លែង" + "សកម្មភាព និងព្រឹត្តិការណ៍" + "វត្ថុ" + "និមិត្តសញ្ញា" + "ទង់" + "មិនមាន​រូប​អារម្មណ៍ទេ" + "អ្នក​មិនទាន់​បានប្រើរូប​អារម្មណ៍​ណាមួយ​នៅឡើយទេ" + "មុខងារប្ដូរទ្វេទិសនៃរូប​អារម្មណ៍" + "បានប្ដូរទិសដៅបែររបស់រូប​អារម្មណ៍" + "ផ្ទាំងជ្រើសរើសជម្រើសរូប​អារម្មណ៍" + "%1$s និង %2$s" + "ស្រមោល" + "សម្បុរស្បែក​ស" + "សម្បុរស្បែក​សល្មម" + "សម្បុរ​ស្បែក​ល្មម" + "សម្បុរ​ស្បែកខ្មៅល្មម" + "សម្បុរ​ស្បែក​ខ្មៅ" + diff --git a/emojipicker/src/main/res/values-kn/strings.xml b/emojipicker/src/main/res/values-kn/strings.xml new file mode 100644 index 000000000..b05a64c2c --- /dev/null +++ b/emojipicker/src/main/res/values-kn/strings.xml @@ -0,0 +1,42 @@ + + + + + "ಇತ್ತೀಚೆಗೆ ಬಳಸಿರುವುದು" + "ಸ್ಮೈಲಿಗಳು ಮತ್ತು ಭಾವನೆಗಳು" + "ಜನರು" + "ಪ್ರಾಣಿಗಳು ಮತ್ತು ಪ್ರಕೃತಿ" + "ಆಹಾರ ಮತ್ತು ಪಾನೀಯ" + "ಪ್ರಯಾಣ ಮತ್ತು ಸ್ಥಳಗಳು" + "ಚಟುವಟಿಕೆಗಳು ಮತ್ತು ಈವೆಂಟ್‌ಗಳು" + "ವಸ್ತುಗಳು" + "ಸಂಕೇತಗಳು" + "ಫ್ಲ್ಯಾಗ್‌ಗಳು" + "ಯಾವುದೇ ಎಮೊಜಿಗಳು ಲಭ್ಯವಿಲ್ಲ" + "ನೀವು ಇನ್ನೂ ಯಾವುದೇ ಎಮೋಜಿಗಳನ್ನು ಬಳಸಿಲ್ಲ" + "ಎಮೋಜಿ ಬೈಡೈರೆಕ್ಷನಲ್ ಸ್ವಿಚರ್" + "ಎಮೋಜಿ ಎದುರಿಸುತ್ತಿರುವ ದಿಕ್ಕನ್ನು ಬದಲಾಯಿಸಲಾಗಿದೆ" + "ಎಮೋಜಿ ವೇರಿಯಂಟ್ ಸೆಲೆಕ್ಟರ್" + "%1$s ಮತ್ತು %2$s" + "ನೆರಳು" + "ಲೈಟ್ ಸ್ಕಿನ್ ಟೋನ್" + "ಮೀಡಿಯಮ್ ಲೈಟ್ ಸ್ಕಿನ್ ಟೋನ್" + "ಮೀಡಿಯಮ್ ಸ್ಕಿನ್ ಟೋನ್" + "ಮೀಡಿಯಮ್ ಡಾರ್ಕ್ ಸ್ಕಿನ್ ಟೋನ್" + "ಡಾರ್ಕ್ ಸ್ಕಿನ್ ಟೋನ್" + diff --git a/emojipicker/src/main/res/values-ko/strings.xml b/emojipicker/src/main/res/values-ko/strings.xml new file mode 100644 index 000000000..22cace838 --- /dev/null +++ b/emojipicker/src/main/res/values-ko/strings.xml @@ -0,0 +1,42 @@ + + + + + "최근 사용" + "이모티콘 및 감정" + "사람" + "동물 및 자연" + "식음료" + "여행 및 장소" + "활동 및 이벤트" + "사물" + "기호" + "깃발" + "사용 가능한 그림 이모티콘 없음" + "아직 사용한 이모티콘이 없습니다." + "그림 이모티콘 양방향 전환기" + "이모티콘 방향 전환됨" + "그림 이모티콘 옵션 선택기" + "%1$s 및 %2$s" + "그림자" + "밝은 피부색" + "약간 밝은 피부색" + "중간 피부색" + "약간 어두운 피부색" + "어두운 피부색" + diff --git a/emojipicker/src/main/res/values-ky/strings.xml b/emojipicker/src/main/res/values-ky/strings.xml new file mode 100644 index 000000000..aa3454690 --- /dev/null +++ b/emojipicker/src/main/res/values-ky/strings.xml @@ -0,0 +1,42 @@ + + + + + "АКЫРКЫ КОЛДОНУЛГАНДАР" + "БЫЙТЫКЧАЛАР ЖАНА ЭМОЦИЯЛАР" + "АДАМДАР" + "ЖАНЫБАРЛАР ЖАНА ЖАРАТЫЛЫШ" + "АЗЫК-ТҮЛҮК ЖАНА СУУСУНДУКТАР" + "САЯКАТ ЖАНА ЖЕРЛЕР" + "ИШ-АРАКЕТТЕР ЖАНА ИШ-ЧАРАЛАР" + "ОБЪЕКТТЕР" + "СИМВОЛДОР" + "ЖЕЛЕКТЕР" + "Жеткиликтүү быйтыкчалар жок" + "Бир да быйтыкча колдоно элексиз" + "эки тараптуу быйтыкча которгуч" + "быйтыкчанын багыты которулду" + "быйтыкча тандагыч" + "%1$s жана %2$s" + "көлөкө" + "ачык түстүү тери" + "агыраак түстүү тери" + "орточо түстүү тери" + "орточо кара тору түстүү тери" + "кара тору түстүү тери" + diff --git a/emojipicker/src/main/res/values-lo/strings.xml b/emojipicker/src/main/res/values-lo/strings.xml new file mode 100644 index 000000000..174400e08 --- /dev/null +++ b/emojipicker/src/main/res/values-lo/strings.xml @@ -0,0 +1,42 @@ + + + + + "ໃຊ້ຫຼ້າສຸດ" + "ໜ້າຍິ້ມ ແລະ ຄວາມຮູ້ສຶກ" + "ຜູ້ຄົນ" + "ສັດ ແລະ ທຳມະຊາດ" + "ອາຫານ ແລະ ເຄື່ອງດື່ມ" + "ການເດີນທາງ ແລະ ສະຖານທີ່" + "ການເຄື່ອນໄຫວ ແລະ ກິດຈະກຳ" + "ວັດຖຸ" + "ສັນຍາລັກ" + "ທຸງ" + "ບໍ່ມີອີໂມຈິໃຫ້ນຳໃຊ້" + "ທ່ານຍັງບໍ່ໄດ້ໃຊ້ອີໂມຈິໃດເທື່ອ" + "ຕົວສະຫຼັບອີໂມຈິແບບ 2 ທິດທາງ" + "ປ່ຽນທິດທາງການຫັນໜ້າຂອງອີໂມຈິແລ້ວ" + "ຕົວເລືອກຕົວແປອີໂມຈິ" + "%1$s ແລະ %2$s" + "ເງົາ" + "ສະກິນໂທນແຈ້ງ" + "ສະກິນໂທນແຈ້ງປານກາງ" + "ສະກິນໂທນປານກາງ" + "ສະກິນໂທນມືດປານກາງ" + "ສະກິນໂທນມືດ" + diff --git a/emojipicker/src/main/res/values-lt/strings.xml b/emojipicker/src/main/res/values-lt/strings.xml new file mode 100644 index 000000000..72390ae43 --- /dev/null +++ b/emojipicker/src/main/res/values-lt/strings.xml @@ -0,0 +1,42 @@ + + + + + "NESENIAI NAUDOTI" + "JAUSTUKAI IR EMOCIJOS" + "ŽMONĖS" + "GYVŪNAI IR GAMTA" + "MAISTAS IR GĖRIMAI" + "KELIONĖS IR VIETOS" + "VEIKLA IR ĮVYKIAI" + "OBJEKTAI" + "SIMBOLIAI" + "VĖLIAVOS" + "Nėra jokių pasiekiamų jaustukų" + "Dar nenaudojote jokių jaustukų" + "dvikryptis jaustukų perjungikli" + "perjungta jaustukų nuoroda" + "jaustuko varianto parinkiklis" + "%1$s ir %2$s" + "šešėlis" + "šviesi odos spalva" + "vidutiniškai šviesi odos spalva" + "nei tamsi, nei šviesi odos spalva" + "vidutiniškai tamsi odos spalva" + "tamsi odos spalva" + diff --git a/emojipicker/src/main/res/values-lv/strings.xml b/emojipicker/src/main/res/values-lv/strings.xml new file mode 100644 index 000000000..0fe66ac75 --- /dev/null +++ b/emojipicker/src/main/res/values-lv/strings.xml @@ -0,0 +1,42 @@ + + + + + "NESEN LIETOTAS" + "SMAIDIŅI UN EMOCIJAS" + "PERSONAS" + "DZĪVNIEKI UN DABA" + "ĒDIENI UN DZĒRIENI" + "CEĻOJUMI UN VIETAS" + "PASĀKUMI UN NOTIKUMI" + "OBJEKTI" + "SIMBOLI" + "KAROGI" + "Nav pieejamu emocijzīmju" + "Jūs vēl neesat izmantojis nevienu emocijzīmi" + "emocijzīmju divvirzienu pārslēdzējs" + "mainīts emocijzīmes virziens" + "emocijzīmes varianta atlasītājs" + "%1$s un %2$s" + "ēna" + "gaišs ādas tonis" + "vidēji gaišs ādas tonis" + "vidējs ādas tonis" + "vidēji tumšs ādas tonis" + "tumšs ādas tonis" + diff --git a/emojipicker/src/main/res/values-mk/strings.xml b/emojipicker/src/main/res/values-mk/strings.xml new file mode 100644 index 000000000..b7ceab0f4 --- /dev/null +++ b/emojipicker/src/main/res/values-mk/strings.xml @@ -0,0 +1,42 @@ + + + + + "НЕОДАМНА КОРИСТЕНИ" + "СМЕШКОВЦИ И ЕМОЦИИ" + "ЛУЃЕ" + "ЖИВОТНИ И ПРИРОДА" + "ХРАНА И ПИЈАЛАЦИ" + "ПАТУВАЊЕ И МЕСТА" + "АКТИВНОСТИ И НАСТАНИ" + "ОБЈЕКТИ" + "СИМБОЛИ" + "ЗНАМИЊА" + "Нема достапни емоџија" + "Сѐ уште не сте користеле емоџија" + "двонасочен менувач на емоџија" + "насоката во којашто е свртено емоџито е сменета" + "избирач на варијанти на емоџија" + "%1$s и %2$s" + "сенка" + "светол тон на кожата" + "средно светол тон на кожата" + "среден тон на кожата" + "средно темен тон на кожата" + "темен тон на кожата" + diff --git a/emojipicker/src/main/res/values-ml/strings.xml b/emojipicker/src/main/res/values-ml/strings.xml new file mode 100644 index 000000000..60b985701 --- /dev/null +++ b/emojipicker/src/main/res/values-ml/strings.xml @@ -0,0 +1,42 @@ + + + + + "അടുത്തിടെ ഉപയോഗിച്ചവ" + "സ്മൈലികളും ഇമോഷനുകളും" + "ആളുകൾ" + "മൃഗങ്ങളും പ്രകൃതിയും" + "ഭക്ഷണപാനീയങ്ങൾ" + "യാത്രയും സ്ഥലങ്ങളും" + "ആക്‌റ്റിവിറ്റികളും ഇവന്റുകളും" + "വസ്‌തുക്കൾ" + "ചിഹ്നങ്ങൾ" + "പതാകകൾ" + "ഇമോജികളൊന്നും ലഭ്യമല്ല" + "നിങ്ങൾ ഇതുവരെ ഇമോജികളൊന്നും ഉപയോഗിച്ചിട്ടില്ല" + "ഇമോജി ദ്വിദിശ സ്വിച്ചർ" + "ഇമോജിയുടെ ദിശ മാറ്റി" + "ഇമോജി വേരിയന്റ് സെലക്‌ടർ" + "%1$s, %2$s" + "ഷാഡോ" + "ലൈറ്റ് സ്‌കിൻ ടോൺ" + "മീഡിയം ലൈറ്റ് സ്‌കിൻ ടോൺ" + "മീഡിയം സ്‌കിൻ ടോൺ" + "മീഡിയം ഡാർക്ക് സ്‌കിൻ ടോൺ" + "ഡാർക്ക് സ്‌കിൻ ടോൺ" + diff --git a/emojipicker/src/main/res/values-mn/strings.xml b/emojipicker/src/main/res/values-mn/strings.xml new file mode 100644 index 000000000..6b07ea5ae --- /dev/null +++ b/emojipicker/src/main/res/values-mn/strings.xml @@ -0,0 +1,42 @@ + + + + + "САЯХАН АШИГЛАСАН" + "ИНЭЭМСЭГЛЭЛ БОЛОН СЭТГЭЛ ХӨДЛӨЛ" + "ХҮМҮҮС" + "АМЬТАД БА БАЙГАЛЬ" + "ХООЛ БОЛОН УУХ ЗҮЙЛ" + "АЯЛАЛ БОЛОН ГАЗРУУД" + "ҮЙЛ АЖИЛЛАГАА БОЛОН АРГА ХЭМЖЭЭ" + "ОБЪЕКТ" + "ТЭМДЭГ" + "ТУГ" + "Боломжтой эможи алга" + "Та ямар нэгэн эможи ашиглаагүй байна" + "эможигийн хоёр чиглэлтэй сэлгүүр" + "эможигийн харж буй чиглэлийг сэлгэсэн" + "эможигийн хувилбар сонгогч" + "%1$s болон %2$s" + "сүүдэр" + "цайвар арьсны өнгө" + "дунд зэргийн цайвар арьсны өнгө" + "дунд зэргийн арьсны өнгө" + "дунд зэргийн бараан арьсны өнгө" + "бараан арьсны өнгө" + diff --git a/emojipicker/src/main/res/values-mr/strings.xml b/emojipicker/src/main/res/values-mr/strings.xml new file mode 100644 index 000000000..316b2c485 --- /dev/null +++ b/emojipicker/src/main/res/values-mr/strings.xml @@ -0,0 +1,42 @@ + + + + + "अलीकडे वापरलेला" + "स्मायली आणि भावना" + "लोक" + "प्राणी आणि निसर्ग" + "खाद्यपदार्थ आणि पेय" + "प्रवास आणि ठिकाणे" + "ॲक्टिव्हिटी आणि इव्हेंट" + "ऑब्जेक्ट" + "चिन्हे" + "ध्वज" + "कोणतेही इमोजी उपलब्ध नाहीत" + "तुम्ही अद्याप कोणतेही इमोजी वापरलेले नाहीत" + "इमोजीचा द्विदिश स्विचर" + "दिशा दाखवणारा इमोजी स्विच केला" + "इमोजी व्हेरीयंट सिलेक्टर" + "%1$s आणि %2$s" + "शॅडो" + "उजळ रंगाची त्वचा" + "मध्यम उजळ रंगाची त्वचा" + "मध्यम रंगाची त्वचा" + "मध्यम गडद रंगाची त्वचा" + "गडद रंगाची त्वचा" + diff --git a/emojipicker/src/main/res/values-ms/strings.xml b/emojipicker/src/main/res/values-ms/strings.xml new file mode 100644 index 000000000..d5ecef2db --- /dev/null +++ b/emojipicker/src/main/res/values-ms/strings.xml @@ -0,0 +1,42 @@ + + + + + "DIGUNAKAN BARU-BARU INI" + "SMILEY DAN EMOSI" + "ORANG" + "HAIWAN DAN ALAM SEMULA JADI" + "MAKANAN DAN MINUMAN" + "PERJALANAN DAN TEMPAT" + "AKTIVITI DAN ACARA" + "OBJEK" + "SIMBOL" + "BENDERA" + "Tiada emoji tersedia" + "Anda belum menggunakan mana-mana emoji lagi" + "penukar dwiarah emoji" + "emoji menghadap arah ditukar" + "pemilih varian emoji" + "%1$s dan %2$s" + "bebayang" + "ton kulit cerah" + "ton kulit sederhana cerah" + "ton kulit sederhana" + "ton kulit sederhana gelap" + "ton kulit gelap" + diff --git a/emojipicker/src/main/res/values-my/strings.xml b/emojipicker/src/main/res/values-my/strings.xml new file mode 100644 index 000000000..99fb7ff2a --- /dev/null +++ b/emojipicker/src/main/res/values-my/strings.xml @@ -0,0 +1,42 @@ + + + + + "မကြာသေးမီက သုံးထားသည်များ" + "စမိုင်းလီနှင့် ခံစားချက်များ" + "လူများ" + "တိရစ္ဆာန်များနှင့် သဘာဝ" + "အစားအသောက်" + "ခရီးသွားခြင်းနှင့် အရပ်ဒေသများ" + "လုပ်ဆောင်ချက်နှင့် အစီအစဉ်များ" + "အရာဝတ္ထုများ" + "သင်္ကေတများ" + "အလံများ" + "အီမိုဂျီ မရနိုင်ပါ" + "အီမိုဂျီ အသုံးမပြုသေးပါ" + "အီမိုဂျီ လမ်းကြောင်းနှစ်ခုပြောင်းစနစ်" + "အီမိုဂျီလှည့်သောဘက်ကို ပြောင်းထားသည်" + "အီမိုဂျီမူကွဲ ရွေးချယ်စနစ်" + "%1$s နှင့် %2$s" + "အရိပ်" + "ဖြူသည့် အသားအရောင်" + "အနည်းငယ်ဖြူသည့် အသားအရောင်" + "အလယ်အလတ် အသားအရောင်" + "အနည်းငယ်ညိုသည့် အသားအရောင်" + "ညိုသည့် အသားအရောင်" + diff --git a/emojipicker/src/main/res/values-nb/strings.xml b/emojipicker/src/main/res/values-nb/strings.xml new file mode 100644 index 000000000..368ef416b --- /dev/null +++ b/emojipicker/src/main/res/values-nb/strings.xml @@ -0,0 +1,42 @@ + + + + + "NYLIG BRUKT" + "SMILEFJES OG UTTRYKKSIKONER" + "PERSONER" + "DYR OG NATUR" + "MAT OG DRIKKE" + "REISE OG STEDER" + "AKTIVITETER OG ARRANGEMENTER" + "GJENSTANDER" + "SYMBOLER" + "FLAGG" + "Ingen emojier er tilgjengelige" + "Du har ikke brukt noen emojier ennå" + "toveisvelger for emoji" + "emojiretningen er slått på" + "velger for emojivariant" + "%1$s og %2$s" + "skygge" + "lys hudtone" + "middels lys hudtone" + "middels hudtone" + "middels mørk hudtone" + "mørk hudtone" + diff --git a/emojipicker/src/main/res/values-ne/strings.xml b/emojipicker/src/main/res/values-ne/strings.xml new file mode 100644 index 000000000..50a489be6 --- /dev/null +++ b/emojipicker/src/main/res/values-ne/strings.xml @@ -0,0 +1,42 @@ + + + + + "हालसालै प्रयोग गरिएको" + "स्माइली र भावनाहरू" + "मान्छेहरू" + "पशु र प्रकृति" + "खाद्य तथा पेय पदार्थ" + "यात्रा र ठाउँहरू" + "क्रियाकलाप तथा कार्यक्रमहरू" + "वस्तुहरू" + "चिन्हहरू" + "झन्डाहरू" + "कुनै पनि इमोजी उपलब्ध छैन" + "तपाईंले हालसम्म कुनै पनि इमोजी प्रयोग गर्नुभएको छैन" + "दुवै दिशामा लैजान सकिने स्विचरको इमोजी" + "इमोजी फर्केको दिशा बदलियो" + "इमोजी भेरियन्ट सेलेक्टर" + "%1$s र %2$s" + "छाया" + "छालाको फिक्का रङ" + "छालाको मध्यम फिक्का रङ" + "छालाको मध्यम रङ" + "छालाको मध्यम गाढा रङ" + "छालाको गाढा रङ" + diff --git a/emojipicker/src/main/res/values-nl/strings.xml b/emojipicker/src/main/res/values-nl/strings.xml new file mode 100644 index 000000000..12d8b4054 --- /dev/null +++ b/emojipicker/src/main/res/values-nl/strings.xml @@ -0,0 +1,42 @@ + + + + + "ONLANGS GEBRUIKT" + "SMILEYS EN EMOTIES" + "MENSEN" + "DIEREN EN NATUUR" + "ETEN EN DRINKEN" + "REIZEN EN PLAATSEN" + "ACTIVITEITEN EN EVENEMENTEN" + "OBJECTEN" + "SYMBOLEN" + "VLAGGEN" + "Geen emoji\'s beschikbaar" + "Je hebt nog geen emoji\'s gebruikt" + "bidirectionele emoji-schakelaar" + "richting van emoji omgewisseld" + "emoji-variantkiezer" + "%1$s en %2$s" + "schaduw" + "lichte huidskleur" + "middellichte huidskleur" + "medium huidskleur" + "middeldonkere huidskleur" + "donkere huidskleur" + diff --git a/emojipicker/src/main/res/values-or/strings.xml b/emojipicker/src/main/res/values-or/strings.xml new file mode 100644 index 000000000..30ffd391f --- /dev/null +++ b/emojipicker/src/main/res/values-or/strings.xml @@ -0,0 +1,42 @@ + + + + + "ବର୍ତ୍ତମାନ ବ୍ୟବହାର କରାଯାଇଛି" + "ସ୍ମାଇଲି ଓ ଆବେଗଗୁଡ଼ିକ" + "ଲୋକମାନେ" + "ଜୀବଜନ୍ତୁ ଓ ପ୍ରକୃତି" + "ଖାଦ୍ୟ ଓ ପାନୀୟ" + "ଟ୍ରାଭେଲ ଓ ସ୍ଥାନଗୁଡ଼ିକ" + "କାର୍ଯ୍ୟକଳାପ ଓ ଇଭେଣ୍ଟଗୁଡ଼ିକ" + "ଅବଜେକ୍ଟଗୁଡ଼ିକ" + "ଚିହ୍ନଗୁଡ଼ିକ" + "ଫ୍ଲାଗଗୁଡ଼ିକ" + "କୌଣସି ଇମୋଜି ଉପଲବ୍ଧ ନାହିଁ" + "ଆପଣ ଏପର୍ଯ୍ୟନ୍ତ କୌଣସି ଇମୋଜି ବ୍ୟବହାର କରିନାହାଁନ୍ତି" + "ଇମୋଜିର ବାଇଡାଇରେକ୍ସନାଲ ସୁଇଚର" + "ଇମୋଜି ଫେସିଂ ଦିଗନିର୍ଦ୍ଦେଶ ସୁଇଚ କରାଯାଇଛି" + "ଇମୋଜି ଭାରିଏଣ୍ଟ ଚୟନକାରୀ" + "%1$s ଏବଂ %2$s" + "ସେଡୋ" + "ଲାଇଟ ସ୍କିନ ଟୋନ" + "ମଧ୍ୟମ ଲାଇଟ ସ୍କିନ ଟୋନ" + "ମଧ୍ୟମ ସ୍କିନ ଟୋନ" + "ମଧ୍ୟମ ଡାର୍କ ସ୍କିନ ଟୋନ" + "ଡାର୍କ ସ୍କିନ ଟୋନ" + diff --git a/emojipicker/src/main/res/values-pa/strings.xml b/emojipicker/src/main/res/values-pa/strings.xml new file mode 100644 index 000000000..85db6c7f4 --- /dev/null +++ b/emojipicker/src/main/res/values-pa/strings.xml @@ -0,0 +1,42 @@ + + + + + "ਹਾਲ ਹੀ ਵਿੱਚ ਵਰਤਿਆ ਗਿਆ" + "ਸਮਾਈਲੀ ਅਤੇ ਜਜ਼ਬਾਤ" + "ਲੋਕ" + "ਜਾਨਵਰ ਅਤੇ ਕੁਦਰਤ" + "ਖਾਣਾ ਅਤੇ ਪੀਣਾ" + "ਯਾਤਰਾ ਅਤੇ ਥਾਵਾਂ" + "ਸਰਗਰਮੀਆਂ ਅਤੇ ਇਵੈਂਟ" + "ਵਸਤੂਆਂ" + "ਚਿੰਨ੍ਹ" + "ਝੰਡੇ" + "ਕੋਈ ਇਮੋਜੀ ਉਪਲਬਧ ਨਹੀਂ ਹੈ" + "ਤੁਸੀਂ ਹਾਲੇ ਤੱਕ ਕਿਸੇ ਵੀ ਇਮੋਜੀ ਦੀ ਵਰਤੋਂ ਨਹੀਂ ਕੀਤੀ ਹੈ" + "ਇਮੋਜੀ ਬਾਇਡਾਇਰੈਕਸ਼ਨਲ ਸਵਿੱਚਰ" + "ਇਮੋਜੀ ਦੀ ਦਿਸ਼ਾ ਬਦਲ ਦਿੱਤੀ ਗਈ" + "ਇਮੋਜੀ ਕਿਸਮ ਚੋਣਕਾਰ" + "%1$s ਅਤੇ %2$s" + "ਸ਼ੈਡੋ" + "ਚਮੜੀ ਦਾ ਹਲਕਾ ਰੰਗ" + "ਚਮੜੀ ਦਾ ਦਰਮਿਆਨਾ ਹਲਕਾ ਰੰਗ" + "ਚਮੜੀ ਦਾ ਦਰਮਿਆਨਾ ਰੰਗ" + "ਚਮੜੀ ਦਾ ਦਰਮਿਆਨਾ ਗੂੜ੍ਹਾ ਰੰਗ" + "ਚਮੜੀ ਦਾ ਗੂੜ੍ਹਾ ਰੰਗ" + diff --git a/emojipicker/src/main/res/values-pl/strings.xml b/emojipicker/src/main/res/values-pl/strings.xml new file mode 100644 index 000000000..3ed8bd349 --- /dev/null +++ b/emojipicker/src/main/res/values-pl/strings.xml @@ -0,0 +1,42 @@ + + + + + "OSTATNIO UŻYWANE" + "EMOTIKONY" + "UCZESTNICY" + "ZWIERZĘTA I PRZYRODA" + "JEDZENIE I NAPOJE" + "PODRÓŻE I MIEJSCA" + "DZIAŁANIA I ZDARZENIA" + "PRZEDMIOTY" + "SYMBOLE" + "FLAGI" + "Brak dostępnych emotikonów" + "Żadne emotikony nie zostały jeszcze użyte" + "dwukierunkowy przełącznik emotikonów" + "zmieniono kierunek emotikonów" + "selektor wariantu emotikona" + "%1$s i %2$s" + "cień" + "jasny odcień skóry" + "średnio jasny odcień skóry" + "pośredni odcień skóry" + "średnio ciemny odcień skóry" + "ciemny odcień skóry" + diff --git a/emojipicker/src/main/res/values-pt-rBR/strings.xml b/emojipicker/src/main/res/values-pt-rBR/strings.xml new file mode 100644 index 000000000..5883fcb3c --- /dev/null +++ b/emojipicker/src/main/res/values-pt-rBR/strings.xml @@ -0,0 +1,42 @@ + + + + + "USADOS RECENTEMENTE" + "CARINHAS E EMOTICONS" + "PESSOAS" + "ANIMAIS E NATUREZA" + "COMIDAS E BEBIDAS" + "VIAGENS E LUGARES" + "ATIVIDADES E EVENTOS" + "OBJETOS" + "SÍMBOLOS" + "BANDEIRAS" + "Não há emojis disponíveis" + "Você ainda não usou emojis" + "seletor bidirecional de emojis" + "emoji virado para a direção trocada" + "seletor de variante do emoji" + "%1$s e %2$s" + "sombra" + "tom de pele claro" + "tom de pele médio-claro" + "tom de pele médio" + "tom de pele médio-escuro" + "tom de pele escuro" + diff --git a/emojipicker/src/main/res/values-pt-rPT/strings.xml b/emojipicker/src/main/res/values-pt-rPT/strings.xml new file mode 100644 index 000000000..2ef06acc4 --- /dev/null +++ b/emojipicker/src/main/res/values-pt-rPT/strings.xml @@ -0,0 +1,42 @@ + + + + + "USADOS RECENTEMENTE" + "EMOTICONS E ÍCONES EXPRESSIVOS" + "PESSOAS" + "ANIMAIS E NATUREZA" + "ALIMENTOS E BEBIDAS" + "VIAGENS E LOCAIS" + "ATIVIDADES E EVENTOS" + "OBJETOS" + "SÍMBOLOS" + "BANDEIRAS" + "Nenhum emoji disponível" + "Ainda não utilizou emojis" + "comutador bidirecional de emojis" + "direção voltada para o emoji alterada" + "seletor de variantes de emojis" + "%1$s e %2$s" + "sombra" + "tom de pele claro" + "tom de pele claro médio" + "tom de pele médio" + "tom de pele escuro médio" + "tom de pele escuro" + diff --git a/emojipicker/src/main/res/values-pt/strings.xml b/emojipicker/src/main/res/values-pt/strings.xml new file mode 100644 index 000000000..5883fcb3c --- /dev/null +++ b/emojipicker/src/main/res/values-pt/strings.xml @@ -0,0 +1,42 @@ + + + + + "USADOS RECENTEMENTE" + "CARINHAS E EMOTICONS" + "PESSOAS" + "ANIMAIS E NATUREZA" + "COMIDAS E BEBIDAS" + "VIAGENS E LUGARES" + "ATIVIDADES E EVENTOS" + "OBJETOS" + "SÍMBOLOS" + "BANDEIRAS" + "Não há emojis disponíveis" + "Você ainda não usou emojis" + "seletor bidirecional de emojis" + "emoji virado para a direção trocada" + "seletor de variante do emoji" + "%1$s e %2$s" + "sombra" + "tom de pele claro" + "tom de pele médio-claro" + "tom de pele médio" + "tom de pele médio-escuro" + "tom de pele escuro" + diff --git a/emojipicker/src/main/res/values-ro/strings.xml b/emojipicker/src/main/res/values-ro/strings.xml new file mode 100644 index 000000000..45fad5a7e --- /dev/null +++ b/emojipicker/src/main/res/values-ro/strings.xml @@ -0,0 +1,42 @@ + + + + + "FOLOSITE RECENT" + "EMOTICOANE ȘI EMOȚII" + "PERSOANE" + "ANIMALE ȘI NATURĂ" + "MÂNCARE ȘI BĂUTURĂ" + "CĂLĂTORII ȘI LOCAȚII" + "ACTIVITĂȚI ȘI EVENIMENTE" + "OBIECTE" + "SIMBOLURI" + "STEAGURI" + "Nu sunt disponibile emoji-uri" + "Încă nu ai folosit emoji" + "comutator bidirecțional de emojiuri" + "direcția de orientare a emojiului comutată" + "selector de variante de emoji" + "%1$s și %2$s" + "umbră" + "nuanță deschisă a pielii" + "nuanță deschisă medie a pielii" + "nuanță medie a pielii" + "nuanță închisă medie a pielii" + "nuanță închisă a pielii" + diff --git a/emojipicker/src/main/res/values-ru/strings.xml b/emojipicker/src/main/res/values-ru/strings.xml new file mode 100644 index 000000000..ecf42faa4 --- /dev/null +++ b/emojipicker/src/main/res/values-ru/strings.xml @@ -0,0 +1,42 @@ + + + + + "НЕДАВНИЕ" + "СМАЙЛИКИ И ЭМОЦИИ" + "ЛЮДИ" + "ПРИРОДА И ЖИВОТНЫЕ" + "ЕДА И НАПИТКИ" + "ПУТЕШЕСТВИЯ" + "ДЕЙСТВИЯ И СОБЫТИЯ" + "ОБЪЕКТЫ" + "СИМВОЛЫ" + "ФЛАГИ" + "Нет доступных эмодзи" + "Вы ещё не использовали эмодзи" + "Двухсторонний переключатель эмодзи" + "изменен поворот лица эмодзи" + "выбор вариантов эмодзи" + "%1$s и %2$s" + "теневой" + "светлый оттенок кожи" + "умеренно светлый оттенок кожи" + "нейтральный оттенок кожи" + "умеренно темный оттенок кожи" + "темный оттенок кожи" + diff --git a/emojipicker/src/main/res/values-si/strings.xml b/emojipicker/src/main/res/values-si/strings.xml new file mode 100644 index 000000000..2ecdc77b3 --- /dev/null +++ b/emojipicker/src/main/res/values-si/strings.xml @@ -0,0 +1,42 @@ + + + + + "මෑතදී භාවිත කළ" + "සිනාසීම් සහ චිත්තවේග" + "පුද්ගලයින්" + "සතුන් හා ස්වභාවධර්මය" + "ආහාර පාන" + "සංචාර හා ස්ථාන" + "ක්‍රියාකාරකම් සහ සිදුවීම්" + "වස්තු" + "සංකේත" + "ධජ" + "ඉමොජි කිසිවක් නොලැබේ" + "ඔබ තවමත් කිසිදු ඉමෝජියක් භාවිතා කර නැත" + "ද්විත්ව දිශා ඉමොජි මාරුකරණය" + "ඉමොජි මුහුණ දෙන දිශාව මාරු විය" + "ඉමොජි ප්‍රභේද තෝරකය" + "%1$s සහ %2$s" + "සෙවනැල්ල" + "ලා සමේ වර්ණය" + "මධ්‍යම ලා සම් වර්ණය" + "මධ්‍යම සම් වර්ණය" + "මධ්‍යම අඳුරු සම් වර්ණය" + "අඳුරු සම් වර්ණය" + diff --git a/emojipicker/src/main/res/values-sk/strings.xml b/emojipicker/src/main/res/values-sk/strings.xml new file mode 100644 index 000000000..11ed0eeaa --- /dev/null +++ b/emojipicker/src/main/res/values-sk/strings.xml @@ -0,0 +1,42 @@ + + + + + "NEDÁVNO POUŽITÉ" + "SMAJLÍKY A EMÓCIE" + "ĽUDIA" + "ZVIERATÁ A PRÍRODA" + "JEDLO A NÁPOJE" + "CESTOVANIE A MIESTA" + "AKTIVITY A UDALOSTI" + "PREDMETY" + "SYMBOLY" + "VLAJKY" + "Nie sú k dispozícii žiadne emodži" + "Zatiaľ ste nepoužili žiadne emodži" + "obojsmerný prepínač emodži" + "smer otočenia emodži bol prepnutý" + "selektor variantu emodži" + "%1$s a %2$s" + "tieň" + "svetlý odtieň pokožky" + "stredne svetlý odtieň pokožky" + "stredný odtieň pokožky" + "stredne tmavý odtieň pokožky" + "tmavý odtieň pokožky" + diff --git a/emojipicker/src/main/res/values-sl/strings.xml b/emojipicker/src/main/res/values-sl/strings.xml new file mode 100644 index 000000000..f345226d0 --- /dev/null +++ b/emojipicker/src/main/res/values-sl/strings.xml @@ -0,0 +1,42 @@ + + + + + "NEDAVNO UPORABLJENI" + "ČUSTVENI SIMBOLI IN ČUSTVA" + "OSEBE" + "ŽIVALI IN NARAVA" + "HRANA IN PIJAČA" + "POTOVANJE IN MESTA" + "DEJAVNOSTI IN DOGODKI" + "PREDMETI" + "SIMBOLI" + "ZASTAVE" + "Ni emodžijev" + "Uporabili niste še nobenega emodžija." + "dvosmerni preklopnik emodžijev" + "preklopljena usmerjenost emodžija" + "Izbirnik različice emodžija" + "%1$s in %2$s" + "senčenje" + "svetel odtenek kože" + "srednje svetel odtenek kože" + "srednji odtenek kože" + "srednje temen odtenek kože" + "temen odtenek kože" + diff --git a/emojipicker/src/main/res/values-sq/strings.xml b/emojipicker/src/main/res/values-sq/strings.xml new file mode 100644 index 000000000..f30f751ef --- /dev/null +++ b/emojipicker/src/main/res/values-sq/strings.xml @@ -0,0 +1,42 @@ + + + + + "PËRDORUR SË FUNDI" + "BUZËQESHJE DHE EMOCIONE" + "NJERËZ" + "KAFSHË DHE NATYRË" + "USHQIME DHE PIJE" + "UDHËTIME DHE VENDE" + "AKTIVITETE DHE NGJARJE" + "OBJEKTE" + "SIMBOLE" + "FLAMUJ" + "Nuk ofrohen emoji" + "Nuk ke përdorur ende asnjë emoji" + "ndërruesi me dy drejtime për emoji-t" + "drejtimi i emoji-t u ndryshua" + "përzgjedhësi i variantit të emoji-t" + "%1$s dhe %2$s" + "hije" + "ton lëkure i zbehtë" + "ton lëkure mesatarisht i zbehtë" + "ton lëkure mesatar" + "ton lëkure mesatarisht i errët" + "ton lëkure i errët" + diff --git a/emojipicker/src/main/res/values-sr/strings.xml b/emojipicker/src/main/res/values-sr/strings.xml new file mode 100644 index 000000000..67d3619f0 --- /dev/null +++ b/emojipicker/src/main/res/values-sr/strings.xml @@ -0,0 +1,42 @@ + + + + + "НЕДАВНО КОРИШЋЕНО" + "СМАЈЛИЈИ И ЕМОЦИЈЕ" + "ЉУДИ" + "ЖИВОТИЊЕ И ПРИРОДА" + "ХРАНА И ПИЋЕ" + "ПУТОВАЊА И МЕСТА" + "АКТИВНОСТИ И ДОГАЂАЈИ" + "ОБЈЕКТИ" + "СИМБОЛИ" + "ЗАСТАВЕ" + "Емоџији нису доступни" + "Још нисте користили емоџије" + "двосмерни пребацивач емоџија" + "смер емоџија је промењен" + "бирач варијанти емоџија" + "%1$s и %2$s" + "сенка" + "кожа светле пути" + "кожа средњесветле пути" + "кожа средње пути" + "кожа средњетамне пути" + "кожа тамне пути" + diff --git a/emojipicker/src/main/res/values-sv/strings.xml b/emojipicker/src/main/res/values-sv/strings.xml new file mode 100644 index 000000000..dede0672c --- /dev/null +++ b/emojipicker/src/main/res/values-sv/strings.xml @@ -0,0 +1,42 @@ + + + + + "NYLIGEN ANVÄNDA" + "KÄNSLOIKONER OCH KÄNSLOR" + "PERSONER" + "DJUR OCH NATUR" + "MAT OCH DRYCK" + "RESOR OCH PLATSER" + "AKTIVITETER OCH HÄNDELSER" + "FÖREMÅL" + "SYMBOLER" + "FLAGGOR" + "Inga emojier tillgängliga" + "Du har ännu inte använt emojis" + "dubbelriktad emojiväxlare" + "emojins riktning har bytts" + "Väljare av emoji-varianter" + "%1$s och %2$s" + "skugga" + "ljus hudfärg" + "medelljus hudfärg" + "medelmörk hudfärg" + "mellanmörk hudfärg" + "mörk hudfärg" + diff --git a/emojipicker/src/main/res/values-sw/strings.xml b/emojipicker/src/main/res/values-sw/strings.xml new file mode 100644 index 000000000..3f7e24b06 --- /dev/null +++ b/emojipicker/src/main/res/values-sw/strings.xml @@ -0,0 +1,42 @@ + + + + + "ZILIZOTUMIKA HIVI MAJUZI" + "VICHESHI NA HISIA" + "WATU" + "WANYAMA NA MAZINGIRA" + "VYAKULA NA VINYWAJI" + "SAFARI NA MAENEO" + "SHUGHULI NA MATUKIO" + "VITU" + "ALAMA" + "BENDERA" + "Hakuna emoji zinazopatikana" + "Bado hujatumia emoji zozote" + "kibadilishaji cha emoji cha pande mbili" + "imebadilisha upande ambao emoji inaangalia" + "kiteuzi cha kibadala cha emoji" + "%1$s na %2$s" + "kivuli" + "ngozi ya rangi nyeupe" + "ngozi ya rangi nyeupe kiasi" + "ngozi ya rangi ya maji ya kunde" + "ngozi ya rangi nyeusi kiasi" + "ngozi ya rangi nyeusi" + diff --git a/emojipicker/src/main/res/values-ta/strings.xml b/emojipicker/src/main/res/values-ta/strings.xml new file mode 100644 index 000000000..5954c77f6 --- /dev/null +++ b/emojipicker/src/main/res/values-ta/strings.xml @@ -0,0 +1,42 @@ + + + + + "சமீபத்தில் பயன்படுத்தியவை" + "ஸ்மைலிகளும் எமோடிகான்களும்" + "நபர்" + "விலங்குகளும் இயற்கையும்" + "உணவும் பானமும்" + "பயணமும் இடங்களும்" + "செயல்பாடுகளும் நிகழ்வுகளும்" + "பொருட்கள்" + "சின்னங்கள்" + "கொடிகள்" + "ஈமோஜிகள் எதுவுமில்லை" + "இதுவரை ஈமோஜி எதையும் நீங்கள் பயன்படுத்தவில்லை" + "ஈமோஜி இருபக்க மாற்றி" + "ஈமோஜி காட்டப்படும் திசை மாற்றப்பட்டது" + "ஈமோஜி வகைத் தேர்வி" + "%1$s மற்றும் %2$s" + "நிழல்" + "வெள்ளை நிறம்" + "கொஞ்சம் வெள்ளை நிறம்" + "மாநிறம்" + "கொஞ்சம் கருநிறம்" + "கருநிறம்" + diff --git a/emojipicker/src/main/res/values-te/strings.xml b/emojipicker/src/main/res/values-te/strings.xml new file mode 100644 index 000000000..db21e73a6 --- /dev/null +++ b/emojipicker/src/main/res/values-te/strings.xml @@ -0,0 +1,42 @@ + + + + + "ఇటీవల ఉపయోగించినవి" + "స్మైలీలు, ఎమోషన్‌లు" + "వ్యక్తులు" + "జంతువులు, ప్రకృతి" + "ఆహారం, పానీయం" + "ప్రయాణం, స్థలాలు" + "యాక్టివిటీలు, ఈవెంట్‌లు" + "ఆబ్జెక్ట్‌లు" + "గుర్తులు" + "ఫ్లాగ్‌లు" + "ఎమోజీలు ఏవీ అందుబాటులో లేవు" + "మీరు ఇంకా ఎమోజీలు ఏవీ ఉపయోగించలేదు" + "ఎమోజీ ద్విదిశాత్మక స్విచ్చర్" + "ఎమోజీ దిశ మార్చబడింది" + "ఎమోజి రకాన్ని ఎంపిక చేసే సాధనం" + "%1$s, %2$s" + "షాడో" + "లైట్ స్కిన్ రంగు" + "చామనఛాయ లైట్ స్కిన్ రంగు" + "చామనఛాయ స్కిన్ రంగు" + "చామనఛాయ డార్క్ స్కిన్ రంగు" + "డార్క్ స్కిన్ రంగు" + diff --git a/emojipicker/src/main/res/values-th/strings.xml b/emojipicker/src/main/res/values-th/strings.xml new file mode 100644 index 000000000..74d28694e --- /dev/null +++ b/emojipicker/src/main/res/values-th/strings.xml @@ -0,0 +1,42 @@ + + + + + "ใช้ล่าสุด" + "หน้ายิ้มและอารมณ์" + "ผู้คน" + "สัตว์และธรรมชาติ" + "อาหารและเครื่องดื่ม" + "การเดินทางและสถานที่" + "กิจกรรมและเหตุการณ์" + "วัตถุ" + "สัญลักษณ์" + "ธง" + "ไม่มีอีโมจิ" + "คุณยังไม่ได้ใช้อีโมจิเลย" + "ตัวสลับอีโมจิแบบ 2 ทาง" + "เปลี่ยนทิศทางการหันหน้าของอีโมจิแล้ว" + "ตัวเลือกตัวแปรอีโมจิ" + "%1$s และ %2$s" + "เงา" + "โทนผิวสีอ่อน" + "โทนผิวสีอ่อนปานกลาง" + "โทนผิวสีปานกลาง" + "โทนผิวสีเข้มปานกลาง" + "โทนผิวสีเข้ม" + diff --git a/emojipicker/src/main/res/values-tl/strings.xml b/emojipicker/src/main/res/values-tl/strings.xml new file mode 100644 index 000000000..2a14fba77 --- /dev/null +++ b/emojipicker/src/main/res/values-tl/strings.xml @@ -0,0 +1,42 @@ + + + + + "KAMAKAILANG GINAMIT" + "MGA SMILEY AT MGA EMOSYON" + "MGA TAO" + "MGA HAYOP AT KALIKASAN" + "PAGKAIN AT INUMIN" + "PAGLALAKBAY AT MGA LUGAR" + "MGA AKTIBIDAD AT EVENT" + "MGA BAGAY" + "MGA SIMBOLO" + "MGA BANDILA" + "Walang available na emoji" + "Hindi ka pa gumamit ng anumang emoji" + "bidirectional na switcher ng emoji" + "pinalitan ang direksyon kung saan nakaharap ang emoji" + "selector ng variant ng emoji" + "%1$s at %2$s" + "shadow" + "maputing kulay ng balat" + "katamtamang maputing kulay ng balat" + "katamtamang kulay ng balat" + "katamtamang maitim na kulay ng balat" + "maitim na kulay ng balat" + diff --git a/emojipicker/src/main/res/values-tr/strings.xml b/emojipicker/src/main/res/values-tr/strings.xml new file mode 100644 index 000000000..f0d13cddf --- /dev/null +++ b/emojipicker/src/main/res/values-tr/strings.xml @@ -0,0 +1,42 @@ + + + + + "SON KULLANILANLAR" + "SMILEY\'LER VE İFADELER" + "İNSANLAR" + "HAYVANLAR VE DOĞA" + "YİYECEK VE İÇECEK" + "SEYAHAT VE YERLER" + "AKTİVİTELER VE ETKİNLİKLER" + "NESNELER" + "SEMBOLLER" + "BAYRAKLAR" + "Kullanılabilir emoji yok" + "Henüz emoji kullanmadınız" + "çift yönlü emoji değiştirici" + "emoji yönü değiştirildi" + "emoji varyant seçici" + "%1$s ve %2$s" + "gölge" + "açık ten rengi" + "orta-açık ten rengi" + "orta ten rengi" + "orta-koyu ten rengi" + "koyu ten rengi" + diff --git a/emojipicker/src/main/res/values-uk/strings.xml b/emojipicker/src/main/res/values-uk/strings.xml new file mode 100644 index 000000000..46e9e3dcd --- /dev/null +++ b/emojipicker/src/main/res/values-uk/strings.xml @@ -0,0 +1,42 @@ + + + + + "НЕЩОДАВНО ВИКОРИСТАНІ" + "СМАЙЛИКИ Й ЕМОЦІЇ" + "ЛЮДИ" + "ТВАРИНИ Й ПРИРОДА" + "ЇЖА Й НАПОЇ" + "ПОДОРОЖІ Й МІСЦЯ" + "АКТИВНІСТЬ І ПОДІЇ" + "ОБ’ЄКТИ" + "СИМВОЛИ" + "ПРАПОРИ" + "Немає смайлів" + "Ви ще не використовували смайли" + "двосторонній перемикач смайлів" + "змінено напрям обличчя смайлів" + "засіб вибору варіанта смайла" + "%1$s і %2$s" + "тінь" + "світлий відтінок шкіри" + "помірно світлий відтінок шкіри" + "помірний відтінок шкіри" + "помірно темний відтінок шкіри" + "темний відтінок шкіри" + diff --git a/emojipicker/src/main/res/values-ur/strings.xml b/emojipicker/src/main/res/values-ur/strings.xml new file mode 100644 index 000000000..68fa937dd --- /dev/null +++ b/emojipicker/src/main/res/values-ur/strings.xml @@ -0,0 +1,42 @@ + + + + + "حال ہی میں استعمال کردہ" + "اسمائلیز اور جذبات" + "لوگ" + "جانور اور قدرت" + "خوراک اور مشروب" + "سفر اور جگہیں" + "سرگرمیاں اور ایونٹس" + "آبجیکٹس" + "علامات" + "جھنڈے" + "کوئی بھی ایموجی دستیاب نہیں ہے" + "آپ نے ابھی تک کوئی بھی ایموجی استعمال نہیں کی ہے" + "دو طرفہ سوئچر ایموجی" + "ایموجی کا سمتِ رخ سوئچ کر دیا گیا" + "ایموجی کی قسم کا منتخب کنندہ" + "‏‎%1$s اور ‎%2$s" + "پرچھائیں" + "جلد کا ہلکا ٹون" + "جلد کا متوسط ہلکا ٹون" + "جلد کا متوسط ٹون" + "جلد کا متوسط گہرا ٹون" + "جلد کا گہرا ٹون" + diff --git a/emojipicker/src/main/res/values-uz/strings.xml b/emojipicker/src/main/res/values-uz/strings.xml new file mode 100644 index 000000000..6610ffd50 --- /dev/null +++ b/emojipicker/src/main/res/values-uz/strings.xml @@ -0,0 +1,42 @@ + + + + + "YAQINDA ISHLATILGAN" + "KULGICH VA EMOJILAR" + "ODAMLAR" + "HAYVONLAR VA TABIAT" + "TAOM VA ICHIMLIKLAR" + "SAYOHAT VA JOYLAR" + "HODISA VA TADBIRLAR" + "BUYUMLAR" + "BELGILAR" + "BAYROQCHALAR" + "Hech qanday emoji mavjud emas" + "Hanuz birorta emoji ishlatmagansiz" + "ikki tomonlama emoji almashtirgich" + "emoji yuzlanish tomoni almashdi" + "emoji variant tanlagich" + "%1$s va %2$s" + "soya" + "och rang tusli" + "oʻrtacha och rang tusli" + "neytral rang tusli" + "oʻrtacha toʻq rang tusli" + "toʻq rang tusli" + diff --git a/emojipicker/src/main/res/values-vi/strings.xml b/emojipicker/src/main/res/values-vi/strings.xml new file mode 100644 index 000000000..9e1eac8ec --- /dev/null +++ b/emojipicker/src/main/res/values-vi/strings.xml @@ -0,0 +1,42 @@ + + + + + "MỚI DÙNG GẦN ĐÂY" + "MẶT CƯỜI VÀ BIỂU TƯỢNG CẢM XÚC" + "MỌI NGƯỜI" + "ĐỘNG VẬT VÀ THIÊN NHIÊN" + "THỰC PHẨM VÀ ĐỒ UỐNG" + "DU LỊCH VÀ ĐỊA ĐIỂM" + "HOẠT ĐỘNG VÀ SỰ KIỆN" + "ĐỒ VẬT" + "BIỂU TƯỢNG" + "CỜ" + "Không có biểu tượng cảm xúc nào" + "Bạn chưa sử dụng biểu tượng cảm xúc nào" + "trình chuyển đổi hai chiều biểu tượng cảm xúc" + "đã chuyển hướng mặt của biểu tượng cảm xúc" + "bộ chọn biến thể biểu tượng cảm xúc" + "%1$s và %2$s" + "bóng" + "tông màu da sáng" + "tông màu da sáng trung bình" + "tông màu da trung bình" + "tông màu da tối trung bình" + "tông màu da tối" + diff --git a/emojipicker/src/main/res/values-zh-rCN/strings.xml b/emojipicker/src/main/res/values-zh-rCN/strings.xml new file mode 100644 index 000000000..453eb005a --- /dev/null +++ b/emojipicker/src/main/res/values-zh-rCN/strings.xml @@ -0,0 +1,42 @@ + + + + + "最近使用过" + "表情符号" + "人物" + "动物和自然" + "食品和饮料" + "旅游和地点" + "活动和庆典" + "物体" + "符号" + "旗帜" + "没有可用的表情符号" + "您尚未使用过任何表情符号" + "表情符号双向切换器" + "已切换表情符号朝向" + "表情符号变体选择器" + "%1$s和%2$s" + "阴影" + "浅肤色" + "中等偏浅肤色" + "中等肤色" + "中等偏深肤色" + "深肤色" + diff --git a/emojipicker/src/main/res/values-zh-rHK/strings.xml b/emojipicker/src/main/res/values-zh-rHK/strings.xml new file mode 100644 index 000000000..21b7318ff --- /dev/null +++ b/emojipicker/src/main/res/values-zh-rHK/strings.xml @@ -0,0 +1,42 @@ + + + + + "最近使用過" + "表情符號" + "人物" + "動物和大自然" + "飲食" + "旅遊和地點" + "活動和事件" + "物件" + "符號" + "旗幟" + "沒有可用的 Emoji" + "你尚未使用任何 Emoji" + "Emoji 雙向切換工具" + "轉咗 Emoji 方向" + "Emoji 變化版本選取器" + "%1$s和%2$s" + "陰影" + "淺膚色" + "偏淺膚色" + "中等膚色" + "偏深膚色" + "深膚色" + diff --git a/emojipicker/src/main/res/values-zh-rTW/strings.xml b/emojipicker/src/main/res/values-zh-rTW/strings.xml new file mode 100644 index 000000000..546e9de25 --- /dev/null +++ b/emojipicker/src/main/res/values-zh-rTW/strings.xml @@ -0,0 +1,42 @@ + + + + + "最近使用過" + "表情符號" + "人物" + "動物與大自然" + "飲食" + "旅行與地點" + "活動與事件" + "物品" + "符號" + "旗幟" + "沒有可用的表情符號" + "你尚未使用任何表情符號" + "表情符號雙向切換器" + "已切換表情符號方向" + "表情符號變化版本選取器" + "%1$s和%2$s" + "陰影" + "淺膚色" + "偏淺膚色" + "中等膚色" + "偏深膚色" + "深膚色" + diff --git a/emojipicker/src/main/res/values-zu/strings.xml b/emojipicker/src/main/res/values-zu/strings.xml new file mode 100644 index 000000000..3918f298b --- /dev/null +++ b/emojipicker/src/main/res/values-zu/strings.xml @@ -0,0 +1,42 @@ + + + + + "EZISANDA KUSETSHENZISWA" + "AMASMAYILI NEMIZWA" + "ABANTU" + "IZILWANE NENDALO" + "UKUDLA NESIPHUZO" + "UKUVAKASHA NEZINDAWO" + "IMISEBENZI NEMICIMBI" + "IZINTO" + "AMASIMBULI" + "AMAFULEGI" + "Awekho ama-emoji atholakalayo" + "Awukasebenzisi noma yimaphi ama-emoji okwamanje" + "isishintshi se-emoji ye-bidirectional" + "isikhombisi-ndlela esibheke ku-emoji sishintshiwe" + "isikhethi esihlukile se-emoji" + "Okuthi %1$s nokuthi %2$s" + "isithunzi" + "ibala lesikhumba elikhanyayo" + "ibala lesikhumba elikhanya ngokumaphakathi" + "ibala lesikhumba eliphakathi nendawo" + "ibala lesikhumba elinsundu ngokumaphakathi" + "ibala lesikhumba elimnyama" + diff --git a/emojipicker/src/main/res/values/arrays.xml b/emojipicker/src/main/res/values/arrays.xml new file mode 100644 index 000000000..8c1328962 --- /dev/null +++ b/emojipicker/src/main/res/values/arrays.xml @@ -0,0 +1,54 @@ + + + + + + @raw/emoji_category_emotions + @raw/emoji_category_people + @raw/emoji_category_animals_nature + @raw/emoji_category_food_drink + @raw/emoji_category_travel_places + @raw/emoji_category_activity + @raw/emoji_category_objects + @raw/emoji_category_symbols + @raw/emoji_category_flags + + + + + @raw/emoji_category_emotions + + @raw/emoji_category_animals_nature + @raw/emoji_category_food_drink + @raw/emoji_category_travel_places + @raw/emoji_category_activity + @raw/emoji_category_objects + @raw/emoji_category_symbols + @raw/emoji_category_flags + + + + @drawable/gm_filled_emoji_emotions_vd_theme_24 + @drawable/gm_filled_emoji_people_vd_theme_24 + @drawable/gm_filled_emoji_nature_vd_theme_24 + @drawable/gm_filled_emoji_food_beverage_vd_theme_24 + @drawable/gm_filled_emoji_transportation_vd_theme_24 + @drawable/gm_filled_emoji_events_vd_theme_24 + @drawable/gm_filled_emoji_objects_vd_theme_24 + @drawable/gm_filled_emoji_symbols_vd_theme_24 + @drawable/gm_filled_flag_vd_theme_24 + + + + @string/emoji_category_emotions + @string/emoji_category_people + @string/emoji_category_animals_nature + @string/emoji_category_food_drink + @string/emoji_category_travel_places + @string/emoji_category_activity + @string/emoji_category_objects + @string/emoji_category_symbols + @string/emoji_category_flags + + \ No newline at end of file diff --git a/emojipicker/src/main/res/values/attrs.xml b/emojipicker/src/main/res/values/attrs.xml new file mode 100644 index 000000000..8804c3eb9 --- /dev/null +++ b/emojipicker/src/main/res/values/attrs.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/main/res/values/colors.xml b/emojipicker/src/main/res/values/colors.xml new file mode 100644 index 000000000..62ab68f23 --- /dev/null +++ b/emojipicker/src/main/res/values/colors.xml @@ -0,0 +1,12 @@ + + + + + #edbd82 + #ba8f63 + #91674d + #875334 + #4a2f27 + + #ffffff + diff --git a/emojipicker/src/main/res/values/dimens.xml b/emojipicker/src/main/res/values/dimens.xml new file mode 100644 index 000000000..fb44ef4da --- /dev/null +++ b/emojipicker/src/main/res/values/dimens.xml @@ -0,0 +1,24 @@ + + + + + 39dp + 46dp + 20dp + 20dp + 28dp + 2dp + 42dp + 5dp + 5dp + 5dp + 10dp + 10dp + 10dp + 8dp + 30dp + 6dp + 24dp + 4dp + 2dp + \ No newline at end of file diff --git a/emojipicker/src/main/res/values/strings.xml b/emojipicker/src/main/res/values/strings.xml new file mode 100644 index 000000000..ddfd2110c --- /dev/null +++ b/emojipicker/src/main/res/values/strings.xml @@ -0,0 +1,61 @@ + + + + + RECENTLY USED + + SMILEYS AND EMOTIONS + + PEOPLE + + ANIMALS AND NATURE + + FOOD AND DRINK + + TRAVEL AND PLACES + + ACTIVITIES AND EVENTS + + OBJECTS + + SYMBOLS + + FLAGS + + + No emojis available + + You haven\'t used any emojis yet + + + emoji bidirectional switcher + + + emoji facing direction switched + + + emoji variant selector + + + %1$s and %2$s + + + shadow + + + light skin tone + + + medium light skin tone + + + medium skin tone + + + medium dark skin tone + + + dark skin tone + diff --git a/emojipicker/src/main/res/values/styles.xml b/emojipicker/src/main/res/values/styles.xml new file mode 100644 index 000000000..7f7fd86a4 --- /dev/null +++ b/emojipicker/src/main/res/values/styles.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + diff --git a/emojipicker/src/test/java/com/rishabh/emojipicker/ExampleUnitTest.kt b/emojipicker/src/test/java/com/rishabh/emojipicker/ExampleUnitTest.kt new file mode 100644 index 000000000..a2585b6ee --- /dev/null +++ b/emojipicker/src/test/java/com/rishabh/emojipicker/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package com.rishabh.emojipicker + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5489d1dfb..346d298ea 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,13 +15,19 @@ gradlePlugins-agp = "8.1.1" #build app-build-compileSDKVersion = "34" app-build-targetSDK = "34" -app-build-minimumSDK = "23" +app-build-minimumSDK = "24" app-build-javaVersion = "VERSION_17" app-build-kotlinJVMTarget = "17" #versioning app-version-appId = "com.simplemobiletools.keyboard" app-version-versionCode = "24" app-version-versionName = "5.4.9" +coreKtx = "1.13.1" +junit = "4.13.2" +junitVersion = "1.2.1" +espressoCore = "3.6.1" +appcompat = "1.7.0" +material = "1.12.0" [libraries] #AndroidX androidx-autofill = { module = "androidx.autofill:autofill", version.ref = "androidx-autofill" } @@ -32,6 +38,12 @@ androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" } androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" } #Simple Mobile Tools simple-tools-commons = { module = "com.github.SimpleMobileTools:Simple-Commons", version.ref = "simple-commons" } +androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } +junit = { group = "junit", name = "junit", version.ref = "junit" } +androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } +androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } +androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } +material = { group = "com.google.android.material", name = "material", version.ref = "material" } [bundles] room = [ "androidx-room-ktx", @@ -41,3 +53,4 @@ room = [ android = { id = "com.android.application", version.ref = "gradlePlugins-agp" } kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } +androidLibrary = { id = "com.android.library", version.ref = "gradlePlugins-agp" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 45478cbec..0aad46001 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -14,3 +14,4 @@ dependencyResolutionManagement { } } include(":app") +include(":emojipicker")