mirror of https://github.com/zulip/zulip.git
user_status: Add UI changes for status emoji feature.
In this commit, we update the UI to:
* Display emoji on the buddy list (right side sidebar).
* Display the emoji picker on the set status overlay.
It also updates the `z-index` of
`#set_user_status_modal`, which was changed from 105
to 1050 in 166bfa4cf8
. We change it back to 105, so
emoji-popover can be visible on top of the
`#set_user_status_modal`.
We also remove the `tabindex` property from the
`#set_user_status_modal` so it can allow keyboard
events for emoji popover.
This commit is contained in:
parent
840ab92f7f
commit
297379029d
|
@ -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() {
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
<div id="set_user_status_modal" class="modal modal-bg hide fade new-style" tabindex="-1" role="dialog" aria-labelledby="set_user_status_modal_label" aria-hidden="true">
|
||||
<div id="set_user_status_modal" class="modal modal-bg hide fade new-style" role="dialog" aria-labelledby="set_user_status_modal_label" aria-hidden="true">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close close-modal-btn" data-dismiss="modal" aria-label="{{t 'Close' }}"><span aria-hidden="true">×</span></button>
|
||||
<h3 id="set_user_status_modal_label">{{t "Set status" }} </h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<label for="user_status">{{t "Status message" }}</label>
|
||||
<input type="text" class="user_status" maxlength="60" />
|
||||
<button type="button" class="btn clear_search_button" id="clear_status_message_button" disabled="disabled">
|
||||
<i class="fa fa-remove" aria-hidden="true"></i>
|
||||
</button>
|
||||
<div class="user_status_content_wrapper">
|
||||
<div class="status_emoji_wrapper tippy-zulip-tooltip" data-tippy-content="{{t 'Click to change' }}" data-tippy-placement="top" aria-label="{{t 'Click to change' }}" tabindex="0" id="selected_emoji">
|
||||
{{> status_emoji_selector}}
|
||||
</div>
|
||||
<input type="text" class="user_status" maxlength="60"/>
|
||||
<button type="button" class="btn clear_search_button" id="clear_status_message_button" disabled="disabled">
|
||||
<i class="fa fa-remove" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="user-status-options">
|
||||
<button type="button" class="button no-style user-status-value">{{t "In a meeting" }}</button>
|
||||
<button type="button" class="button no-style user-status-value">{{t "Commuting" }}</button>
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
{{#if selected_emoji}}
|
||||
{{#if selected_emoji.emoji_alt_code}}
|
||||
<div class="emoji_alt_code"> :{{selected_emoji.emoji_name}}:</div>
|
||||
{{else}}
|
||||
{{#if selected_emoji.url}}
|
||||
<img src="{{selected_emoji.url}}" class="emoji selected_emoji" />
|
||||
{{else}}
|
||||
<div class="emoji selected_emoji emoji-{{selected_emoji.emoji_code}}"></div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<a type="button" class="smiley_icon status_emoji show fa fa-smile-o"></a>
|
||||
{{/if}}
|
|
@ -5,9 +5,17 @@
|
|||
href="{{href}}"
|
||||
data-user-id="{{user_id}}"
|
||||
data-name="{{name}}">
|
||||
{{name}}
|
||||
{{#if my_user_status}}
|
||||
<span class="my_user_status">{{my_user_status}}</span>
|
||||
<span class="user-name">{{name}}</span>
|
||||
{{#if status_emoji_info}}
|
||||
{{#if status_emoji_info.emoji_alt_code}}
|
||||
<div class="emoji_alt_code"> :{{status_emoji_info.emoji_name}}:</div>
|
||||
{{else}}
|
||||
{{#if status_emoji_info.url}}
|
||||
<img src="{{status_emoji_info.url}}" class="emoji status_emoji" />
|
||||
{{else}}
|
||||
<div class="emoji status_emoji emoji-{{status_emoji_info.emoji_code}}"></div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</a>
|
||||
<span class="unread_count">{{#if num_unread}}{{num_unread}}{{/if}}</span>
|
||||
|
|
Loading…
Reference in New Issue