feat(chat): emoji picker as an in-pane overlay with keyword search
Reworked the emoji picker from a floating popup (which overlapped the message area) into an overlay that takes over the conversation-list pane while open: a Cancel button + a keyword search box at the top, then a responsive grid below that wraps to the pane width. Each emoji now carries search keywords (grin/heart/fire/…) so the search box filters the ~150-emoji set. The 🙂 composer button toggles the overlay; selecting an emoji appends it to the composer (byte-cap respected) and the overlay stays open for multiple picks. +1 CJK glyph (絵) for the ja "Search emoji" string. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Binary file not shown.
@@ -139,6 +139,7 @@
|
|||||||
"chat_cancel": "Abbrechen",
|
"chat_cancel": "Abbrechen",
|
||||||
"chat_contact_added": "Kontakt hinzugefügt – benenne ihn in Kontakte um",
|
"chat_contact_added": "Kontakt hinzugefügt – benenne ihn in Kontakte um",
|
||||||
"chat_contact_request": "kontaktanfrage",
|
"chat_contact_request": "kontaktanfrage",
|
||||||
|
"chat_emoji_search": "Emoji suchen",
|
||||||
"chat_empty_hint": "Noch keine Unterhaltungen. Nachrichten, die du erhältst, erscheinen hier.",
|
"chat_empty_hint": "Noch keine Unterhaltungen. Nachrichten, die du erhältst, erscheinen hier.",
|
||||||
"chat_empty_start": "Starte eine mit \"Neue Unterhaltung\".",
|
"chat_empty_start": "Starte eine mit \"Neue Unterhaltung\".",
|
||||||
"chat_empty_title": "Noch keine Unterhaltungen",
|
"chat_empty_title": "Noch keine Unterhaltungen",
|
||||||
|
|||||||
@@ -139,6 +139,7 @@
|
|||||||
"chat_cancel": "Cancelar",
|
"chat_cancel": "Cancelar",
|
||||||
"chat_contact_added": "Contacto añadido: renómbralo en Contactos",
|
"chat_contact_added": "Contacto añadido: renómbralo en Contactos",
|
||||||
"chat_contact_request": "solicitud de contacto",
|
"chat_contact_request": "solicitud de contacto",
|
||||||
|
"chat_emoji_search": "Buscar emoji",
|
||||||
"chat_empty_hint": "Aún no hay conversaciones. Los mensajes que recibas aparecerán aquí.",
|
"chat_empty_hint": "Aún no hay conversaciones. Los mensajes que recibas aparecerán aquí.",
|
||||||
"chat_empty_start": "Inicia una con \"Nueva conversación\".",
|
"chat_empty_start": "Inicia una con \"Nueva conversación\".",
|
||||||
"chat_empty_title": "Aún no hay conversaciones",
|
"chat_empty_title": "Aún no hay conversaciones",
|
||||||
|
|||||||
@@ -139,6 +139,7 @@
|
|||||||
"chat_cancel": "Annuler",
|
"chat_cancel": "Annuler",
|
||||||
"chat_contact_added": "Contact ajouté — renommez-le dans Contacts",
|
"chat_contact_added": "Contact ajouté — renommez-le dans Contacts",
|
||||||
"chat_contact_request": "demande de contact",
|
"chat_contact_request": "demande de contact",
|
||||||
|
"chat_emoji_search": "Rechercher un emoji",
|
||||||
"chat_empty_hint": "Aucune conversation pour l'instant. Les messages que vous recevez apparaîtront ici.",
|
"chat_empty_hint": "Aucune conversation pour l'instant. Les messages que vous recevez apparaîtront ici.",
|
||||||
"chat_empty_start": "Commencez-en une avec « Nouvelle conversation ».",
|
"chat_empty_start": "Commencez-en une avec « Nouvelle conversation ».",
|
||||||
"chat_empty_title": "Aucune conversation pour l'instant",
|
"chat_empty_title": "Aucune conversation pour l'instant",
|
||||||
|
|||||||
@@ -139,6 +139,7 @@
|
|||||||
"chat_cancel": "キャンセル",
|
"chat_cancel": "キャンセル",
|
||||||
"chat_contact_added": "連絡先を追加しました — 連絡先で名前を変更できます",
|
"chat_contact_added": "連絡先を追加しました — 連絡先で名前を変更できます",
|
||||||
"chat_contact_request": "連絡リクエスト",
|
"chat_contact_request": "連絡リクエスト",
|
||||||
|
"chat_emoji_search": "絵文字を検索",
|
||||||
"chat_empty_hint": "まだ会話はありません。受信したメッセージはここに表示されます。",
|
"chat_empty_hint": "まだ会話はありません。受信したメッセージはここに表示されます。",
|
||||||
"chat_empty_start": "「新しい会話」から始めましょう。",
|
"chat_empty_start": "「新しい会話」から始めましょう。",
|
||||||
"chat_empty_title": "会話はまだありません",
|
"chat_empty_title": "会話はまだありません",
|
||||||
|
|||||||
@@ -139,6 +139,7 @@
|
|||||||
"chat_cancel": "취소",
|
"chat_cancel": "취소",
|
||||||
"chat_contact_added": "연락처 추가됨 — 연락처에서 이름을 변경하세요",
|
"chat_contact_added": "연락처 추가됨 — 연락처에서 이름을 변경하세요",
|
||||||
"chat_contact_request": "연락 요청",
|
"chat_contact_request": "연락 요청",
|
||||||
|
"chat_emoji_search": "이모지 검색",
|
||||||
"chat_empty_hint": "아직 대화가 없습니다. 받은 메시지가 여기에 표시됩니다.",
|
"chat_empty_hint": "아직 대화가 없습니다. 받은 메시지가 여기에 표시됩니다.",
|
||||||
"chat_empty_start": "\"새 대화\"로 시작하세요.",
|
"chat_empty_start": "\"새 대화\"로 시작하세요.",
|
||||||
"chat_empty_title": "아직 대화가 없습니다",
|
"chat_empty_title": "아직 대화가 없습니다",
|
||||||
|
|||||||
@@ -139,6 +139,7 @@
|
|||||||
"chat_cancel": "Cancelar",
|
"chat_cancel": "Cancelar",
|
||||||
"chat_contact_added": "Contato adicionado — renomeie em Contatos",
|
"chat_contact_added": "Contato adicionado — renomeie em Contatos",
|
||||||
"chat_contact_request": "solicitação de contato",
|
"chat_contact_request": "solicitação de contato",
|
||||||
|
"chat_emoji_search": "Pesquisar emoji",
|
||||||
"chat_empty_hint": "Nenhuma conversa ainda. As mensagens que você receber aparecerão aqui.",
|
"chat_empty_hint": "Nenhuma conversa ainda. As mensagens que você receber aparecerão aqui.",
|
||||||
"chat_empty_start": "Inicie uma com \"Nova conversa\".",
|
"chat_empty_start": "Inicie uma com \"Nova conversa\".",
|
||||||
"chat_empty_title": "Ainda não há conversas",
|
"chat_empty_title": "Ainda não há conversas",
|
||||||
|
|||||||
@@ -139,6 +139,7 @@
|
|||||||
"chat_cancel": "Отмена",
|
"chat_cancel": "Отмена",
|
||||||
"chat_contact_added": "Контакт добавлен — переименуйте его в Контактах",
|
"chat_contact_added": "Контакт добавлен — переименуйте его в Контактах",
|
||||||
"chat_contact_request": "запрос контакта",
|
"chat_contact_request": "запрос контакта",
|
||||||
|
"chat_emoji_search": "Поиск эмодзи",
|
||||||
"chat_empty_hint": "Пока нет переписок. Полученные сообщения появятся здесь.",
|
"chat_empty_hint": "Пока нет переписок. Полученные сообщения появятся здесь.",
|
||||||
"chat_empty_start": "Начните новый с помощью «Новый разговор».",
|
"chat_empty_start": "Начните новый с помощью «Новый разговор».",
|
||||||
"chat_empty_title": "Пока нет разговоров",
|
"chat_empty_title": "Пока нет разговоров",
|
||||||
|
|||||||
@@ -139,6 +139,7 @@
|
|||||||
"chat_cancel": "取消",
|
"chat_cancel": "取消",
|
||||||
"chat_contact_added": "已添加联系人——可在联系人中重命名",
|
"chat_contact_added": "已添加联系人——可在联系人中重命名",
|
||||||
"chat_contact_request": "联系人请求",
|
"chat_contact_request": "联系人请求",
|
||||||
|
"chat_emoji_search": "搜索表情",
|
||||||
"chat_empty_hint": "暂无对话。您收到的消息将显示在此处。",
|
"chat_empty_hint": "暂无对话。您收到的消息将显示在此处。",
|
||||||
"chat_empty_start": "点击\"新建会话\"开始。",
|
"chat_empty_start": "点击\"新建会话\"开始。",
|
||||||
"chat_empty_title": "还没有会话",
|
"chat_empty_title": "还没有会话",
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ char s_new_zaddr[128] = "";
|
|||||||
char s_new_msg[256] = "";
|
char s_new_msg[256] = "";
|
||||||
char s_search[80] = ""; // conversation-list filter (Q8)
|
char s_search[80] = ""; // conversation-list filter (Q8)
|
||||||
bool s_show_hidden = false; // when on, the list also shows hidden conversations (with an Unhide action)
|
bool s_show_hidden = false; // when on, the list also shows hidden conversations (with an Unhide action)
|
||||||
|
bool s_show_emoji_picker = false; // emoji picker overlay — fills the conversation-list pane while open
|
||||||
|
char s_emoji_search[48] = ""; // emoji picker keyword filter
|
||||||
|
|
||||||
// Effective draw-list font size for a material font (mirrors sidebar's ScaledFontSize).
|
// Effective draw-list font size for a material font (mirrors sidebar's ScaledFontSize).
|
||||||
float scaledSize(ImFont* f) { return f->LegacySize * ImGui::GetStyle().FontScaleMain; }
|
float scaledSize(ImFont* f) { return f->LegacySize * ImGui::GetStyle().FontScaleMain; }
|
||||||
@@ -201,40 +203,75 @@ void centeredEmptyState(const char* icon, const char* title, const char* hint) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emoji picker popup: a scrollable grid of common single-codepoint emoji (verified present in the
|
// Common single-codepoint emoji (all verified present in the bundled NotoEmoji subset), each with
|
||||||
// bundled NotoEmoji subset). Clicking one appends its UTF-8 bytes to `buf` (respecting the buffer).
|
// keyword text for the picker's search box. Single-codepoint only — ImGui does no shaping, so ZWJ
|
||||||
// The set is single-codepoint only — ImGui does no shaping, so ZWJ sequences / flags wouldn't compose.
|
// sequences / flags wouldn't compose.
|
||||||
void emojiPickerPopup(const char* popupId, char* buf, std::size_t bufSize) {
|
struct EmojiEntry { const char* glyph; const char* keywords; };
|
||||||
static const char* const kEmoji =
|
static const EmojiEntry kEmoji[] = {
|
||||||
u8"😀😃😄😁😆😅😂🤣😊😇🙂🙃😉😌😍🥰😘😗😙😚😋😛😝😜🤪🤨🧐🤓😎🥳😏😒😞😔😟😕🙁😣😖😫😩🥺😢😭😤"
|
{u8"😀","grin happy smile"},{u8"😃","smile happy joy"},{u8"😄","laugh happy smile"},{u8"😁","grin beam happy"},
|
||||||
u8"😠😡🤬🤯😳🥵🥶😱😨😰😥😓🤗🤔🤭🤫🤥😶😐😑😬🙄😯😦😧😮😲🥱😴🤤😪🤐🥴🤢🤮🤧😷🤒🤕😈👿💀👻👽🤖😺🙀"
|
{u8"😆","laugh haha"},{u8"😅","sweat laugh nervous"},{u8"😂","joy laugh tears cry funny"},{u8"🤣","rofl laugh rolling funny"},
|
||||||
u8"👍👎👌✌🤞🤟🤘👏🙌👐🙏💪👋🤙👊✊🤛🤜👆👇👈👉"
|
{u8"😊","blush smile happy"},{u8"😇","angel innocent halo"},{u8"🙂","slight smile"},{u8"🙃","upside down silly"},
|
||||||
u8"❤🧡💛💚💙💜🖤🤍💔💕💞💗💖💘💝🔥⭐🎉🎊✨💯✅❌❓❗👀🎂🚀💰🎁🍺🍻☕🍕👑💎🌟💥";
|
{u8"😉","wink"},{u8"😌","relieved calm"},{u8"😍","heart eyes love"},{u8"🥰","love hearts adore"},{u8"😘","kiss blow"},
|
||||||
const float dp = Layout::dpiScale();
|
{u8"😗","kiss"},{u8"😙","kiss smile"},{u8"😚","kiss closed"},{u8"😋","yum tasty tongue"},{u8"😛","tongue playful"},
|
||||||
ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, 260.0f * dp)); // cap height → scrolls
|
{u8"😝","tongue squint"},{u8"😜","wink tongue crazy"},{u8"🤪","zany crazy silly"},{u8"🤨","raised eyebrow suspicious"},
|
||||||
if (!ImGui::BeginPopup(popupId)) return;
|
{u8"🧐","monocle thinking"},{u8"🤓","nerd geek glasses"},{u8"😎","cool sunglasses"},{u8"🥳","party celebrate hat"},
|
||||||
|
{u8"😏","smirk"},{u8"😒","unamused meh"},{u8"😞","disappointed sad"},{u8"😔","pensive sad"},{u8"😟","worried"},
|
||||||
|
{u8"😕","confused"},{u8"🙁","frown sad"},{u8"😣","persevere"},{u8"😖","confounded"},{u8"😫","tired"},{u8"😩","weary"},
|
||||||
|
{u8"🥺","pleading puppy beg"},{u8"😢","cry sad tear"},{u8"😭","sob cry bawl"},{u8"😤","huff triumph steam"},
|
||||||
|
{u8"😠","angry mad"},{u8"😡","rage mad angry"},{u8"🤬","curse swear angry"},{u8"🤯","mind blown shock"},
|
||||||
|
{u8"😳","flushed embarrassed"},{u8"🥵","hot heat sweat"},{u8"🥶","cold freezing"},{u8"😱","scream fear shock"},
|
||||||
|
{u8"😨","fearful scared"},{u8"😰","anxious sweat"},{u8"😥","sad sweat"},{u8"😓","sweat"},{u8"🤗","hug"},
|
||||||
|
{u8"🤔","think hmm"},{u8"🤭","giggle oops hand"},{u8"🤫","shush quiet"},{u8"🤥","lie"},{u8"😶","no mouth blank"},
|
||||||
|
{u8"😐","neutral meh"},{u8"😑","expressionless"},{u8"😬","grimace awkward"},{u8"🙄","eye roll"},{u8"😯","hushed surprise"},
|
||||||
|
{u8"😦","frown open"},{u8"😧","anguished"},{u8"😮","wow surprise oh"},{u8"😲","astonished shock"},{u8"🥱","yawn tired bored"},
|
||||||
|
{u8"😴","sleep zzz"},{u8"🤤","drool"},{u8"😪","sleepy"},{u8"🤐","zipper quiet secret"},{u8"🥴","woozy dizzy drunk"},
|
||||||
|
{u8"🤢","nausea sick"},{u8"🤮","vomit sick"},{u8"🤧","sneeze sick"},{u8"😷","mask sick"},{u8"🤒","sick thermometer"},
|
||||||
|
{u8"🤕","hurt bandage injured"},{u8"😈","devil imp evil"},{u8"👿","devil angry"},{u8"💀","skull dead"},{u8"👻","ghost boo"},
|
||||||
|
{u8"👽","alien"},{u8"🤖","robot bot"},{u8"😺","cat smile"},{u8"🙀","cat scream"},
|
||||||
|
{u8"👍","thumbs up like yes good"},{u8"👎","thumbs down dislike no bad"},{u8"👌","ok perfect"},{u8"✌","peace victory"},
|
||||||
|
{u8"🤞","fingers crossed luck"},{u8"🤟","love you"},{u8"🤘","rock horns"},{u8"👏","clap applause"},
|
||||||
|
{u8"🙌","raise hands celebrate"},{u8"👐","open hands"},{u8"🙏","pray thanks please"},{u8"💪","muscle strong flex"},
|
||||||
|
{u8"👋","wave hi hello bye"},{u8"🤙","call shaka"},{u8"👊","fist punch bump"},{u8"✊","fist raised"},{u8"🤛","fist left"},
|
||||||
|
{u8"🤜","fist right"},{u8"👆","up point"},{u8"👇","down point"},{u8"👈","left point"},{u8"👉","right point"},
|
||||||
|
{u8"❤","heart red love"},{u8"🧡","heart orange"},{u8"💛","heart yellow"},{u8"💚","heart green"},{u8"💙","heart blue"},
|
||||||
|
{u8"💜","heart purple"},{u8"🖤","heart black"},{u8"🤍","heart white"},{u8"💔","broken heart"},{u8"💕","hearts love"},
|
||||||
|
{u8"💞","revolving hearts"},{u8"💗","growing heart"},{u8"💖","sparkling heart"},{u8"💘","heart arrow cupid"},
|
||||||
|
{u8"💝","heart gift ribbon"},{u8"🔥","fire lit hot flame"},{u8"⭐","star"},{u8"🎉","party tada celebrate confetti"},
|
||||||
|
{u8"🎊","confetti party"},{u8"✨","sparkles shiny"},{u8"💯","hundred perfect 100"},{u8"✅","check yes done tick"},
|
||||||
|
{u8"❌","cross no wrong x"},{u8"❓","question mark"},{u8"❗","exclamation mark"},{u8"👀","eyes look"},{u8"🎂","cake birthday"},
|
||||||
|
{u8"🚀","rocket launch"},{u8"💰","money bag cash"},{u8"🎁","gift present"},{u8"🍺","beer"},{u8"🍻","beers cheers"},
|
||||||
|
{u8"☕","coffee tea"},{u8"🍕","pizza"},{u8"👑","crown king queen"},{u8"💎","diamond gem"},{u8"🌟","glowing star"},
|
||||||
|
{u8"💥","boom explosion"},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Emoji picker overlay: fills the conversation-list pane (cancel + keyword search at the top, then a
|
||||||
|
// grid). Clicking an emoji appends its UTF-8 bytes to `buf` (the composer), respecting the buffer.
|
||||||
|
void renderEmojiPickerOverlay(char* buf, std::size_t bufSize) {
|
||||||
|
if (ImGui::SmallButton(TR("chat_cancel"))) { s_show_emoji_picker = false; s_emoji_search[0] = '\0'; return; }
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::SetNextItemWidth(-FLT_MIN);
|
||||||
|
ImGui::InputTextWithHint("##emojisearch", TR("chat_emoji_search"), s_emoji_search, sizeof(s_emoji_search));
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
const std::string q = s_emoji_search;
|
||||||
|
ImGui::BeginChild("##emojigrid", ImVec2(0, 0), false);
|
||||||
ImGui::PushFont(material::Type().subtitle1()); // larger + emoji-capable
|
ImGui::PushFont(material::Type().subtitle1()); // larger + emoji-capable
|
||||||
const float cell = 30.0f * dp;
|
const float cell = 32.0f * Layout::dpiScale();
|
||||||
const int perRow = 9;
|
const float step = cell + ImGui::GetStyle().ItemSpacing.x;
|
||||||
int idx = 0;
|
const int perRow = std::max(1, static_cast<int>(ImGui::GetContentRegionAvail().x / step));
|
||||||
for (const char* s = kEmoji; *s;) {
|
int shown = 0;
|
||||||
const unsigned char lead = static_cast<unsigned char>(*s);
|
for (const auto& e : kEmoji) {
|
||||||
const int len = (lead >= 0xF0) ? 4 : (lead >= 0xE0) ? 3 : (lead >= 0xC0) ? 2 : 1;
|
if (!q.empty() && !containsCI(e.keywords, q)) continue;
|
||||||
char glyph[5] = {0};
|
ImGui::PushID(shown);
|
||||||
for (int k = 0; k < len && s[k]; ++k) glyph[k] = s[k];
|
if (ImGui::Button(e.glyph, ImVec2(cell, cell))) {
|
||||||
ImGui::PushID(idx);
|
const std::size_t cur = std::strlen(buf), add = std::strlen(e.glyph);
|
||||||
if (ImGui::Button(glyph, ImVec2(cell, cell))) {
|
if (cur + add < bufSize) { std::memcpy(buf + cur, e.glyph, add); buf[cur + add] = '\0'; }
|
||||||
const std::size_t cur = std::strlen(buf);
|
|
||||||
const std::size_t add = std::strlen(glyph);
|
|
||||||
if (cur + add < bufSize) { std::memcpy(buf + cur, glyph, add); buf[cur + add] = '\0'; }
|
|
||||||
}
|
}
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
if ((idx + 1) % perRow != 0) ImGui::SameLine();
|
if (++shown % perRow != 0) ImGui::SameLine();
|
||||||
s += len;
|
|
||||||
++idx;
|
|
||||||
}
|
}
|
||||||
ImGui::PopFont();
|
ImGui::PopFont();
|
||||||
ImGui::EndPopup();
|
ImGui::EndChild();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@@ -310,7 +347,10 @@ void RenderChatTab(App* app)
|
|||||||
// Faint sidebar tint so the list reads as distinct from the thread pane (V6).
|
// Faint sidebar tint so the list reads as distinct from the thread pane (V6).
|
||||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::ColorConvertU32ToFloat4(material::WithAlpha(material::OnSurface(), 10)));
|
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::ColorConvertU32ToFloat4(material::WithAlpha(material::OnSurface(), 10)));
|
||||||
ImGui::BeginChild("##ChatList", ImVec2(listW, avail.y), true);
|
ImGui::BeginChild("##ChatList", ImVec2(listW, avail.y), true);
|
||||||
{
|
if (s_show_emoji_picker) {
|
||||||
|
// Emoji picker overlay takes over the conversation-list pane while open (search + cancel + grid).
|
||||||
|
renderEmojiPickerOverlay(s_compose, sizeof(s_compose));
|
||||||
|
} else {
|
||||||
// Accented "New conversation" action (house tactile style).
|
// Accented "New conversation" action (house tactile style).
|
||||||
ImGui::PushStyleColor(ImGuiCol_Button, ImGui::ColorConvertU32ToFloat4(material::WithAlpha(material::Primary(), 205)));
|
ImGui::PushStyleColor(ImGuiCol_Button, ImGui::ColorConvertU32ToFloat4(material::WithAlpha(material::Primary(), 205)));
|
||||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::ColorConvertU32ToFloat4(material::Primary()));
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::ColorConvertU32ToFloat4(material::Primary()));
|
||||||
@@ -656,12 +696,12 @@ void RenderChatTab(App* app)
|
|||||||
if (material::TactileButton(TR("chat_send"), ImVec2(sendW, composerBoxH))) submit = true;
|
if (material::TactileButton(TR("chat_send"), ImVec2(sendW, composerBoxH))) submit = true;
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
ImGui::PopStyleColor(3);
|
ImGui::PopStyleColor(3);
|
||||||
// Emoji picker button (left) + byte counter (right) on one row.
|
// Emoji picker button (left) + byte counter (right) on one row. The picker opens as an
|
||||||
|
// overlay over the conversation-list pane (rendered there), not a floating window.
|
||||||
ImGui::PushFont(nameFont); // Body2 has emoji merged, so the glyph renders
|
ImGui::PushFont(nameFont); // Body2 has emoji merged, so the glyph renders
|
||||||
const bool emojiClicked = ImGui::SmallButton(u8"🙂");
|
const bool emojiClicked = ImGui::SmallButton(u8"🙂");
|
||||||
ImGui::PopFont();
|
ImGui::PopFont();
|
||||||
if (emojiClicked) ImGui::OpenPopup("##emojipick");
|
if (emojiClicked) { s_show_emoji_picker = !s_show_emoji_picker; s_emoji_search[0] = '\0'; }
|
||||||
emojiPickerPopup("##emojipick", s_compose, sizeof(s_compose));
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
// Byte counter (Error tint over cap) with the over-cap label.
|
// Byte counter (Error tint over cap) with the over-cap label.
|
||||||
ImGui::PushFont(metaFont);
|
ImGui::PushFont(metaFont);
|
||||||
|
|||||||
@@ -255,6 +255,7 @@ void I18n::loadBuiltinEnglish()
|
|||||||
strings_["chat_hide"] = "Hide";
|
strings_["chat_hide"] = "Hide";
|
||||||
strings_["chat_unhide"] = "Unhide";
|
strings_["chat_unhide"] = "Unhide";
|
||||||
strings_["chat_show_hidden"] = "Show hidden";
|
strings_["chat_show_hidden"] = "Show hidden";
|
||||||
|
strings_["chat_emoji_search"] = "Search emoji";
|
||||||
strings_["chat_hide_hidden"] = "Hide hidden";
|
strings_["chat_hide_hidden"] = "Hide hidden";
|
||||||
strings_["chat_hidden_toast"] = "Conversation hidden — a new message brings it back";
|
strings_["chat_hidden_toast"] = "Conversation hidden — a new message brings it back";
|
||||||
strings_["chat_pick_contact"] = "Choose from contacts\xE2\x80\xA6";
|
strings_["chat_pick_contact"] = "Choose from contacts\xE2\x80\xA6";
|
||||||
|
|||||||
Reference in New Issue
Block a user