diff --git a/static/js/emoji_picker.js b/static/js/emoji_picker.js index 9ef99aea07..692bcbd6b4 100644 --- a/static/js/emoji_picker.js +++ b/static/js/emoji_picker.js @@ -12,6 +12,7 @@ import * as blueslip from "./blueslip"; import * as compose_ui from "./compose_ui"; import * as message_lists from "./message_lists"; import * as message_store from "./message_store"; +import {page_params} from "./page_params"; import * as popovers from "./popovers"; import * as reactions from "./reactions"; import * as rows from "./rows"; @@ -190,6 +191,12 @@ export function reactions_popped() { export function hide_emoji_popover() { $(".has_popover").removeClass("has_popover has_emoji_popover"); + if (user_status_ui.user_status_picker_open()) { + // Re-enable clicking events for other elements after closing + // the popover. This is the inverse of the hack of in the + // handler that opens the "user status modal" emoji picker. + $(".app, .header, .modal-backdrop, #set_user_status_modal").css("pointer-events", "all"); + } if (reactions_popped()) { current_message_emoji_popover_elem.popover("destroy"); current_message_emoji_popover_elem.removeClass("reaction_button_visible"); @@ -761,6 +768,31 @@ export function register_click_handlers() { true, ); }); + + $("body").on("click", "#set_user_status_modal #selected_emoji", (e) => { + e.preventDefault(); + e.stopPropagation(); + toggle_emoji_popover(e.target); + // Because the emoji picker gets drawn on top of the user + // status modal, we need this hack to make clicking outside + // the emoji picker only close the emoji picker, and not the + // whole user status modal. + $(".app, .header, .modal-backdrop, #set_user_status_modal").css("pointer-events", "none"); + }); + + $(document).on("click", ".emoji-popover-emoji.status_emoji", function (e) { + e.preventDefault(); + e.stopPropagation(); + hide_emoji_popover(); + const emoji_name = $(this).attr("data-emoji-name"); + let emoji_info = {emoji_name, emoji_alt_code: page_params.emojiset === "text"}; + if (!emoji_info.emoji_alt_code) { + emoji_info = {...emoji_info, ...emoji.get_emoji_details_by_name(emoji_name)}; + } + user_status_ui.set_selected_emoji_info(emoji_info); + user_status_ui.update_button(); + user_status_ui.toggle_clear_message_button(); + }); } export function initialize() { diff --git a/static/js/user_status_ui.js b/static/js/user_status_ui.js index f95964ae89..e4ef21dfea 100644 --- a/static/js/user_status_ui.js +++ b/static/js/user_status_ui.js @@ -1,11 +1,19 @@ import $ from "jquery"; +import * as emoji from "../shared/js/emoji"; import render_set_status_overlay from "../templates/set_status_overlay.hbs"; +import render_status_emoji_selector from "../templates/status_emoji_selector.hbs"; import * as overlays from "./overlays"; import * as people from "./people"; import * as user_status from "./user_status"; +let selected_emoji_info = {}; + +export function set_selected_emoji_info(emoji_info) { + selected_emoji_info = {...emoji_info}; + rebuild_status_emoji_selector_ui(selected_emoji_info); +} export function input_field() { return $("#set_user_status_modal input.user_status"); } @@ -15,13 +23,19 @@ export function submit_button() { } export function open_user_status_modal() { - const rendered_set_status_overlay = render_set_status_overlay(); + const user_id = people.my_current_user_id(); + const selected_emoji_info = user_status.get_status_emoji(user_id) || {}; + const rendered_set_status_overlay = render_set_status_overlay({ + default_status_messages_and_emoji_info, + selected_emoji_info, + }); $(".app").append(rendered_set_status_overlay); overlays.open_modal("#set_user_status_modal", {autoremove: true}); - const user_id = people.my_current_user_id(); const old_status_text = user_status.get_status_text(user_id); + const old_emoji_info = user_status.get_status_emoji(user_id) || {}; + set_selected_emoji_info(old_emoji_info); const field = input_field(); field.val(old_status_text); field.trigger("select"); @@ -40,15 +54,24 @@ export function submit_new_status() { const user_id = people.my_current_user_id(); let old_status_text = user_status.get_status_text(user_id) || ""; old_status_text = old_status_text.trim(); + const old_emoji_info = user_status.get_status_emoji(user_id) || {}; const new_status_text = input_field().val().trim(); - if (old_status_text === new_status_text) { + if ( + old_status_text === new_status_text && + old_emoji_info.emoji_name === selected_emoji_info.emoji_name && + old_emoji_info.reaction_type === selected_emoji_info.reaction_type && + old_emoji_info.emoji_code === selected_emoji_info.emoji_code + ) { close_user_status_modal(); return; } user_status.server_update({ status_text: new_status_text, + emoji_name: selected_emoji_info.emoji_name || "", + emoji_code: selected_emoji_info.emoji_code || "", + reaction_type: selected_emoji_info.reaction_type || "", success() { close_user_status_modal(); }, @@ -59,10 +82,16 @@ export function update_button() { const user_id = people.my_current_user_id(); let old_status_text = user_status.get_status_text(user_id) || ""; old_status_text = old_status_text.trim(); + const old_emoji_info = user_status.get_status_emoji(user_id) || {}; const new_status_text = input_field().val().trim(); const button = submit_button(); - if (old_status_text === new_status_text) { + if ( + old_status_text === new_status_text && + old_emoji_info.emoji_name === selected_emoji_info.emoji_name && + old_emoji_info.reaction_type === selected_emoji_info.reaction_type && + old_emoji_info.emoji_code === selected_emoji_info.emoji_code + ) { button.prop("disabled", true); } else { button.prop("disabled", false); @@ -70,7 +99,7 @@ export function update_button() { } export function toggle_clear_message_button() { - if (input_field().val() !== "") { + if (input_field().val() !== "" || selected_emoji_info.emoji_name) { $("#clear_status_message_button").prop("disabled", false); } else { $("#clear_status_message_button").prop("disabled", true); @@ -87,6 +116,15 @@ export function user_status_picker_open() { return $("#set_user_status_modal").length !== 0; } +function rebuild_status_emoji_selector_ui(selected_emoji_info) { + let selected_emoji = null; + if (selected_emoji_info && Object.keys(selected_emoji_info).length) { + selected_emoji = selected_emoji_info; + } + const rendered_status_emoji_selector = render_status_emoji_selector({selected_emoji}); + $("#set_user_status_modal .status_emoji_wrapper").html(rendered_status_emoji_selector); +} + export function initialize() { $("body").on("click", ".user-status-value", (event) => { event.stopPropagation(); @@ -115,6 +153,7 @@ export function initialize() { $("body").on("click", "#clear_status_message_button", () => { clear_message(); + set_selected_emoji_info(); update_button(); }); } diff --git a/static/styles/night_mode.css b/static/styles/night_mode.css index 14555f08b8..498c1add9b 100644 --- a/static/styles/night_mode.css +++ b/static/styles/night_mode.css @@ -217,7 +217,8 @@ on a dark background, and don't change the dark labels dark either. */ textarea, .new-style .tab-switcher .ind-tab:not(.selected), select, - .pill-container { + .pill-container, + .user_status_content_wrapper { background-color: hsla(0, 0%, 0%, 0.2); border-color: hsla(0, 0%, 0%, 0.6); color: inherit; diff --git a/static/styles/right_sidebar.css b/static/styles/right_sidebar.css index def9bd6c1f..33372ad7c9 100644 --- a/static/styles/right_sidebar.css +++ b/static/styles/right_sidebar.css @@ -97,8 +97,13 @@ .user-presence-link, .user_sidebar_entry .selectable_sidebar_block { + display: flex; overflow: hidden; - text-overflow: ellipsis; + + .user-name { + overflow: hidden; + text-overflow: ellipsis; + } } .user_sidebar_entry .selectable_sidebar_block { @@ -109,6 +114,17 @@ .user-presence-link { width: calc(100% - 24px); + + .status_emoji { + height: 16px; + width: 16px; + /* We are setting minimum width here because when the user's name is very long, + emoji's width decreases and causes it to break. */ + min-width: 16px; + margin-left: 4px; + margin-right: 4px; + top: 8px; + } } .my_user_status { diff --git a/static/styles/user_status.css b/static/styles/user_status.css index b60f5570da..e601ff2df7 100644 --- a/static/styles/user_status.css +++ b/static/styles/user_status.css @@ -9,16 +9,51 @@ left: 50%; transform: translate(-50%, -50%); margin-left: 0; + /* We are setting a z-index so emoji popover can be visible on top of it. */ + z-index: 105; + .user_status_content_wrapper { + display: flex; + border: 1px solid; + border-color: hsla(0, 0%, 0%, 0.6); + border-radius: 5px; - input.user_status { - width: 94%; - @media (width < $ml_min) { - width: 93%; + input.user_status { + width: 95%; + border: none; + background-color: transparent; + padding-right: 25px; + @media (width < $ml_min) { + width: 92%; + } + } + .status_emoji_wrapper { + height: 20px; + width: 22px; + padding: 4px 8px 4px 8px; + border-right: 1px solid; + border-color: inherit; + cursor: pointer; + .selected_emoji { + width: 18px; + height: 18px; + top: 4px; + cursor: pointer; + } + .smiley_icon { + display: block; + font-size: 18px; + position: relative; + top: 1px; + left: 2px; + &:hover { + text-decoration: none; + } + } } } .user-status-options { - padding-top: 10px; + padding-top: 15px; padding-left: 2px; button.user-status-value:hover { diff --git a/static/templates/set_status_overlay.hbs b/static/templates/set_status_overlay.hbs index 5d2eb5f368..0f55e067db 100644 --- a/static/templates/set_status_overlay.hbs +++ b/static/templates/set_status_overlay.hbs @@ -1,14 +1,19 @@ -