Merge branch 'message-composer'
429
app/css/app.css
@ -771,7 +771,7 @@ a.tg_radio_on:hover i.icon-radio {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
background: url(../img/icons/General.png) no-repeat -5px -10px;
|
||||
background-size: 40px 678px;
|
||||
background-size: 40px 778px;
|
||||
margin-right: 18px;
|
||||
}
|
||||
.icon-tg-title {
|
||||
@ -809,7 +809,7 @@ a.tg_radio_on:hover i.icon-radio {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
background: url(../img/icons/General.png) no-repeat -18px -50px;
|
||||
background-size: 40px 678px;
|
||||
background-size: 40px 778px;
|
||||
margin-left: 12px;
|
||||
margin-top: -1px;
|
||||
}
|
||||
@ -1453,7 +1453,7 @@ div.im_message_video_thumb {
|
||||
display: inline-block;
|
||||
line-height: 0;
|
||||
background: url(../img/icons/General.png) no-repeat -14px -509px;
|
||||
background-size: 40px 678px;
|
||||
background-size: 40px 778px;
|
||||
width: 12px;
|
||||
height: 18px;
|
||||
margin: 12px 15px;
|
||||
@ -1476,7 +1476,7 @@ div.im_message_video_thumb {
|
||||
width: 14px;
|
||||
height: 16px;
|
||||
background: url(../img/icons/General.png) no-repeat -13px -611px;
|
||||
background-size: 40px 678px;;
|
||||
background-size: 40px 778px;;
|
||||
margin: 13px 16px;
|
||||
}
|
||||
.is_1x .im_message_file_button_dl_audio .im_message_file_button_icon {
|
||||
@ -1775,42 +1775,6 @@ a.im_message_fwd_photo {
|
||||
line-height: 150%;
|
||||
}
|
||||
|
||||
span.emoji {
|
||||
display: -moz-inline-box;
|
||||
-moz-box-orient: vertical;
|
||||
display: inline-block;
|
||||
vertical-align: baseline;
|
||||
*vertical-align: auto;
|
||||
*zoom: 1;
|
||||
*display: inline;
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
background-repeat: no-repeat;
|
||||
text-indent: -9999px;
|
||||
}
|
||||
|
||||
/* widths and heights calculated according to spritesheet dimensions and icon size */
|
||||
.emoji-spritesheet-0 {
|
||||
background-size: 486px 126px;
|
||||
background-image: url('../img/emojisprite_0.png');
|
||||
}
|
||||
.emoji-spritesheet-1 {
|
||||
background-size: 522px 72px;
|
||||
background-image: url('../img/emojisprite_1.png');
|
||||
}
|
||||
.emoji-spritesheet-2 {
|
||||
background-size: 594px 126px;
|
||||
background-image: url('../img/emojisprite_2.png');
|
||||
}
|
||||
.emoji-spritesheet-3 {
|
||||
background-size: 612px 54px;
|
||||
background-image: url('../img/emojisprite_3.png');
|
||||
}
|
||||
.emoji-spritesheet-4 {
|
||||
background-size: 612px 126px;
|
||||
background-image: url('../img/emojisprite_4.png');
|
||||
}
|
||||
|
||||
.im_history_not_selected,
|
||||
.im_history_empty {
|
||||
visibility: hidden;
|
||||
@ -1951,17 +1915,259 @@ img.img_fullsize {
|
||||
|
||||
|
||||
|
||||
/* Emoji area */
|
||||
.emoji-wysiwyg-editor:empty:before {
|
||||
content: attr(placeholder);
|
||||
color: #9aa2ab;
|
||||
/* Message composer */
|
||||
.composer_emoji_insert_btn {
|
||||
display: block;
|
||||
position: absolute;
|
||||
right: 3px;
|
||||
top: 2px;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
.emoji-wysiwyg-editor:active:before,
|
||||
.emoji-wysiwyg-editor:focus:before {
|
||||
content: none;
|
||||
.icon-emoji {
|
||||
display: inline-block;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
vertical-align: top;
|
||||
background: url(../img/icons/General.png) no-repeat -9px -335px;
|
||||
background-size: 40px 778px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
.composer_emoji_tooltip {
|
||||
display: none;
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
width: 220px;
|
||||
margin-left: -100px;
|
||||
margin-top: -248px;
|
||||
|
||||
border: 1px #dfdfdf solid;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
-webkit-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.1);
|
||||
-moz-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.1);
|
||||
background: #FFF;
|
||||
padding: 5px 2px 5px 5px;
|
||||
}
|
||||
.composer_emoji_tooltip_shown {
|
||||
display: block;
|
||||
}
|
||||
.composer_emoji_tooltip_tail {
|
||||
position: absolute;
|
||||
bottom: -14px;
|
||||
left: 50%;
|
||||
margin-left: -13px;
|
||||
overflow: hidden;
|
||||
width: 26px;
|
||||
height: 14px;
|
||||
}
|
||||
.icon-tooltip-tail {
|
||||
background: #FFF;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
-webkit-transform: rotate(45deg);
|
||||
-moz-transform: rotate(45deg);
|
||||
-ms-transform: rotate(45deg);
|
||||
-o-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
display: inline-block;
|
||||
-webkit-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);
|
||||
-moz-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);
|
||||
border: 1px #dfdfdf solid;
|
||||
border-width: 0 1px 1px 0;
|
||||
-webkit-border-radius: 2px;
|
||||
-moz-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
position: relative;
|
||||
top: -8px;
|
||||
left: 4px;
|
||||
|
||||
}
|
||||
|
||||
.emoji-wysiwyg-editor {
|
||||
.composer_emoji_tooltip_tabs {
|
||||
width: 100%;
|
||||
margin-bottom: 8px;
|
||||
margin-top: 3px;
|
||||
}
|
||||
.composer_emoji_tooltip_tab {
|
||||
line-height: 0;
|
||||
color: white;
|
||||
display: inline-block;
|
||||
width: 24px;
|
||||
height: 29px;
|
||||
background: url(../img/icons/IconsetSmiles.png) no-repeat;
|
||||
background-size: 42px 470px;
|
||||
cursor: pointer;
|
||||
opacity: 0.7;
|
||||
margin: 0 3px;
|
||||
}
|
||||
.is_1x .composer_emoji_tooltip_tab {
|
||||
background-image: url(../img/icons/IconsetSmiles_1x.png);
|
||||
}
|
||||
.composer_emoji_tooltip_tab.active {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.composer_emoji_tooltip_tab_recent {background-position: -9px -306px; }
|
||||
.composer_emoji_tooltip_tab_recent.active {background-position: -9px -277px; }
|
||||
|
||||
.composer_emoji_tooltip_tab_smile {background-position: -9px -34px; }
|
||||
.composer_emoji_tooltip_tab_smile.active {background-position: -9px -5px; }
|
||||
|
||||
.composer_emoji_tooltip_tab_flower {background-position: -9px -145px; }
|
||||
.composer_emoji_tooltip_tab_flower.active {background-position: -9px -118px; }
|
||||
|
||||
.composer_emoji_tooltip_tab_bell {background-position: -9px -89px; }
|
||||
.composer_emoji_tooltip_tab_bell.active {background-position: -9px -61px; }
|
||||
|
||||
.composer_emoji_tooltip_tab_car {background-position: -9px -196px; }
|
||||
.composer_emoji_tooltip_tab_car.active {background-position: -9px -170px; }
|
||||
|
||||
.composer_emoji_tooltip_tab_grid {background-position: -9px -248px; }
|
||||
.composer_emoji_tooltip_tab_grid.active {background-position: -9px -222px; }
|
||||
|
||||
.composer_emoji_tooltip_tab_stickers {background-position: -9px -361px; }
|
||||
.composer_emoji_tooltip_tab_stickers.active {background-position: -9px -333px; }
|
||||
|
||||
|
||||
.nano.composer_emoji_tooltip_content_wrap {
|
||||
height: 174px;
|
||||
position: relative;
|
||||
}
|
||||
.composer_emoji_tooltip_content {
|
||||
/*position: relative;*/
|
||||
/*overflow: hidden;
|
||||
overflow-y: auto;*/
|
||||
padding-right: 8px;
|
||||
outline: 0!important;
|
||||
}
|
||||
|
||||
|
||||
a.composer_emoji_btn {
|
||||
margin: -1px 0 0 -1px;
|
||||
padding: 5px;
|
||||
display: block;
|
||||
float: left;
|
||||
border-radius: 2px;
|
||||
}
|
||||
a.composer_emoji_btn:hover {
|
||||
background-color: #edf2f5;
|
||||
}
|
||||
|
||||
.emoji {
|
||||
display: -moz-inline-box;
|
||||
-moz-box-orient: vertical;
|
||||
display: inline-block;
|
||||
vertical-align: baseline;
|
||||
*vertical-align: auto;
|
||||
*zoom: 1;
|
||||
*display: inline;
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
background-repeat: no-repeat;
|
||||
text-indent: -9999px;
|
||||
border: 0 none;
|
||||
}
|
||||
|
||||
/* widths and heights calculated according to spritesheet dimensions and icon size */
|
||||
.emoji-spritesheet-0 {
|
||||
background-size: 486px 126px;
|
||||
background-image: url('../img/emojisprite_0.png');
|
||||
}
|
||||
.emoji-spritesheet-1 {
|
||||
background-size: 522px 72px;
|
||||
background-image: url('../img/emojisprite_1.png');
|
||||
}
|
||||
.emoji-spritesheet-2 {
|
||||
background-size: 594px 126px;
|
||||
background-image: url('../img/emojisprite_2.png');
|
||||
}
|
||||
.emoji-spritesheet-3 {
|
||||
background-size: 612px 54px;
|
||||
background-image: url('../img/emojisprite_3.png');
|
||||
}
|
||||
.emoji-spritesheet-4 {
|
||||
background-size: 612px 126px;
|
||||
background-image: url('../img/emojisprite_4.png');
|
||||
}
|
||||
|
||||
.emoji-w20 {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
}
|
||||
.emoji-w20.emoji-spritesheet-0 {background-size: 540px 140px;}
|
||||
.emoji-w20.emoji-spritesheet-1 {background-size: 580px 80px;}
|
||||
.emoji-w20.emoji-spritesheet-2 {background-size: 660px 140px;}
|
||||
.emoji-w20.emoji-spritesheet-3 {background-size: 680px 60px;}
|
||||
.emoji-w20.emoji-spritesheet-4 {background-size: 680px 140px;}
|
||||
|
||||
.emoji-w26 {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
}
|
||||
.emoji-w26.emoji-spritesheet-0 {background-size: 702px 182px;}
|
||||
.emoji-w26.emoji-spritesheet-1 {background-size: 754px 104px;}
|
||||
.emoji-w26.emoji-spritesheet-2 {background-size: 858px 182px;}
|
||||
.emoji-w26.emoji-spritesheet-3 {background-size: 884px 78px;}
|
||||
.emoji-w26.emoji-spritesheet-4 {background-size: 884px 182px;}
|
||||
|
||||
.composer_dropdown {
|
||||
display: none;
|
||||
/*max-width: 100%;*/
|
||||
border-radius: 2px;
|
||||
padding: 6px 0;
|
||||
border: 1px solid rgba(15, 60, 96, 0.2);
|
||||
-webkit-box-shadow: 0px 1px 3px 0px rgba(60,75,87,0.27);
|
||||
-moz-box-shadow: 0px 1px 3px 0px rgba(60,75,87,0.27);
|
||||
box-shadow: 0px 1px 3px 0px rgba(60,75,87,0.27);
|
||||
}
|
||||
|
||||
.composer_dropdown > li > a {
|
||||
display: block;
|
||||
font-size: 13px;
|
||||
line-height: 15px;
|
||||
padding: 4px 10px;
|
||||
color: #52719a;
|
||||
}
|
||||
.composer_dropdown li a:hover,
|
||||
.composer_dropdown li a.composer_emoji_option_active {
|
||||
color: #52719a;
|
||||
background: #f2f6fa;
|
||||
}
|
||||
.composer_emoji_shortcut {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
margin-left: 15px;
|
||||
line-height: 20px;
|
||||
}
|
||||
.composer_sticker_btn {
|
||||
width: 67px;
|
||||
height: 67px;
|
||||
display: block;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
padding: 3px;
|
||||
}
|
||||
.composer_sticker_btn:hover {
|
||||
background: #f2f6fa;
|
||||
}
|
||||
.composer_sticker_image {
|
||||
max-width: 64px;
|
||||
max-height: 64px;
|
||||
}
|
||||
|
||||
.composer_rich_textarea {
|
||||
box-sizing: content-box;
|
||||
-moz-box-sizing: content-box;
|
||||
font-size: 12px;
|
||||
@ -1989,122 +2195,27 @@ img.img_fullsize {
|
||||
-ms-user-select: text;
|
||||
user-select: text;
|
||||
}
|
||||
.emoji-wysiwyg-editor img {
|
||||
|
||||
.composer_rich_textarea:empty:before {
|
||||
content: attr(placeholder);
|
||||
color: #9aa2ab;
|
||||
}
|
||||
.composer_rich_textarea:active:before,
|
||||
.composer_rich_textarea:focus:before {
|
||||
content: none;
|
||||
}
|
||||
.composer_rich_textarea:empty:active:before,
|
||||
.composer_rich_textarea:empty:focus:before {
|
||||
content: attr(placeholder);
|
||||
color: #9aa2ab;
|
||||
}
|
||||
|
||||
.composer_rich_textarea img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
vertical-align: middle;
|
||||
margin: -3px 0 0 0;
|
||||
}
|
||||
.emoji-menu {
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
width: 220px;
|
||||
margin-left: -107px;
|
||||
margin-top: -252px;
|
||||
overflow: hidden;
|
||||
|
||||
border: 1px #dfdfdf solid;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
overflow: hidden;
|
||||
-webkit-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.1);
|
||||
-moz-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.emoji-items-wrap1 {
|
||||
background: #FFF;
|
||||
padding: 5px 2px 5px 5px;
|
||||
}
|
||||
.emoji-items-wrap1 .emoji-menu-tabs {
|
||||
width: 100%;
|
||||
margin-bottom: 8px;
|
||||
margin-top: 3px;
|
||||
}
|
||||
.emoji-items-wrap1 .emoji-menu-tabs td {
|
||||
text-align: center;
|
||||
color: white;
|
||||
line-height: 0;
|
||||
}
|
||||
.emoji-menu-tabs .emoji-menu-tab {
|
||||
display: inline-block;
|
||||
width: 24px;
|
||||
height: 29px;
|
||||
background: url(../img/icons/IconsetSmiles.png) no-repeat;
|
||||
background-size: 42px 350px;
|
||||
}
|
||||
.is_1x .emoji-menu-tabs .emoji-menu-tab {
|
||||
background-image: url(../img/icons/IconsetSmiles_1x.png);
|
||||
}
|
||||
|
||||
.emoji-menu-tabs .icon-recent {background-position: -9px -306px; }
|
||||
.emoji-menu-tabs .icon-recent-selected {background-position: -9px -277px; }
|
||||
|
||||
.emoji-menu-tabs .icon-smile {background-position: -9px -34px; }
|
||||
.emoji-menu-tabs .icon-smile-selected {background-position: -9px -5px; }
|
||||
|
||||
.emoji-menu-tabs .icon-flower {background-position: -9px -145px; }
|
||||
.emoji-menu-tabs .icon-flower-selected {background-position: -9px -118px; }
|
||||
|
||||
.emoji-menu-tabs .icon-bell {background-position: -9px -89px; }
|
||||
.emoji-menu-tabs .icon-bell-selected {background-position: -9px -61px; }
|
||||
|
||||
.emoji-menu-tabs .icon-car {background-position: -9px -196px; }
|
||||
.emoji-menu-tabs .icon-car-selected {background-position: -9px -170px; }
|
||||
|
||||
.emoji-menu-tabs .icon-grid {background-position: -9px -248px; }
|
||||
.emoji-menu-tabs .icon-grid-selected {background-position: -9px -222px; }
|
||||
|
||||
.emoji-menu-tabs .icon-recent,
|
||||
.emoji-menu-tabs .icon-smile,
|
||||
.emoji-menu-tabs .icon-flower,
|
||||
.emoji-menu-tabs .icon-bell,
|
||||
.emoji-menu-tabs .icon-car,
|
||||
.emoji-menu-tabs .icon-grid {
|
||||
opacity: 0.7;
|
||||
}
|
||||
.emoji-menu-tabs .icon-recent:hover,
|
||||
.emoji-menu-tabs .icon-smile:hover,
|
||||
.emoji-menu-tabs .icon-flower:hover,
|
||||
.emoji-menu-tabs .icon-bell:hover,
|
||||
.emoji-menu-tabs .icon-car:hover,
|
||||
.emoji-menu-tabs .icon-grid:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
||||
.emoji-menu .emoji-items-wrap {
|
||||
position: relative;
|
||||
height: 174px;
|
||||
}
|
||||
.emoji-menu .emoji-items {
|
||||
padding-right: 8px;
|
||||
outline: 0 !important;
|
||||
}
|
||||
.emoji-menu img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
vertical-align: middle;
|
||||
border: 0 none;
|
||||
}
|
||||
.emoji-menu .emoji-items a {
|
||||
margin: -1px 0 0 -1px;
|
||||
padding: 5px;
|
||||
display: block;
|
||||
float: left;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.emoji-menu .emoji-items a:hover {
|
||||
background-color: #edf2f5;
|
||||
}
|
||||
.emoji-menu:after {
|
||||
content: ' ';
|
||||
display: block;
|
||||
clear: left;
|
||||
}
|
||||
.emoji-menu a .label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
.error_modal_window .modal-dialog {
|
||||
|
@ -171,7 +171,7 @@
|
||||
margin-right: 38px;
|
||||
display: inline-block;
|
||||
background: url(../img/icons/General.png) no-repeat -10px -111px;
|
||||
background-size: 40px 678px;
|
||||
background-size: 40px 778px;
|
||||
vertical-align: top;
|
||||
margin-top: 3px;
|
||||
}
|
||||
@ -183,7 +183,7 @@
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
background: url(../img/icons/General.png) no-repeat -11px -135px;
|
||||
background-size: 40px 678px;
|
||||
background-size: 40px 778px;
|
||||
}
|
||||
.icon-settings {
|
||||
width: 20px;
|
||||
@ -193,7 +193,7 @@
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
background: url(../img/icons/General.png) no-repeat -10px -163px;
|
||||
background-size: 40px 678px;
|
||||
background-size: 40px 778px;
|
||||
}
|
||||
.icon-faq {
|
||||
width: 20px;
|
||||
@ -203,7 +203,7 @@
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
background: url(../img/icons/General.png) no-repeat -10px -637px;
|
||||
background-size: 40px 678px;
|
||||
background-size: 40px 778px;
|
||||
}
|
||||
.icon-about {
|
||||
width: 21px;
|
||||
@ -212,7 +212,7 @@
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
background: url(../img/icons/General.png) no-repeat -10px -193px;
|
||||
background-size: 40px 678px;
|
||||
background-size: 40px 778px;
|
||||
}
|
||||
.is_1x .icon-new-group,
|
||||
.is_1x .icon-contacts,
|
||||
@ -315,7 +315,7 @@
|
||||
.icon-filter-audio {
|
||||
display: inline-block;
|
||||
background: url(../img/icons/General.png) no-repeat 0 0;
|
||||
background-size: 40px 678px;
|
||||
background-size: 40px 778px;
|
||||
margin-right: 12px;
|
||||
vertical-align: top;
|
||||
}
|
||||
@ -408,11 +408,11 @@
|
||||
opacity : 0.99;
|
||||
}
|
||||
|
||||
.emoji-menu .nano > .nano-pane {
|
||||
.composer_emoji_tooltip .nano > .nano-pane {
|
||||
background : rgba(255,255,255,0.0);
|
||||
right: -2px;
|
||||
}
|
||||
.emoji-menu .nano > .nano-pane > .nano-slider {
|
||||
.composer_emoji_tooltip .nano > .nano-pane > .nano-slider {
|
||||
background: #d1d1d1;
|
||||
margin: 0 3px 0 4px;
|
||||
}
|
||||
@ -722,26 +722,21 @@ a.footer_link.active:active {
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
.im_emoji_quick_select_area {
|
||||
.composer_emoji_panel {
|
||||
display: block;
|
||||
height: 30px;
|
||||
overflow: hidden;
|
||||
max-width: 210px;
|
||||
}
|
||||
|
||||
.im_emoji_quick_select_area a {
|
||||
.composer_emoji_panel a {
|
||||
display: inline-block;
|
||||
padding: 5px;
|
||||
outline: 0;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.im_emoji_quick_select_area a:hover {
|
||||
/*.composer_emoji_panel a:hover {
|
||||
background-color: #edf2f5;
|
||||
}
|
||||
.im_emoji_quick_select_area a .label {
|
||||
display: none;
|
||||
}
|
||||
}*/
|
||||
|
||||
.im_message_selected .im_message_date,
|
||||
.im_message_selected .im_message_document_size,
|
||||
@ -940,7 +935,8 @@ a.im_panel_peer_photo .peer_initials {
|
||||
margin-left: 36px;
|
||||
}
|
||||
|
||||
.im_emoji_btn {
|
||||
/*.composer_emoji_insert_btn {
|
||||
display: block;
|
||||
position: absolute;
|
||||
right: 3px;
|
||||
top: 2px;
|
||||
@ -950,33 +946,48 @@ a.im_panel_peer_photo .peer_initials {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
.icon-emoji {
|
||||
}*/
|
||||
/*.icon-emoji {
|
||||
display: inline-block;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
vertical-align: top;
|
||||
background: url(../img/icons/General.png) no-repeat -9px -335px;
|
||||
background-size: 40px 678px;
|
||||
background-size: 40px 778px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
}*/
|
||||
.is_1x .icon-emoji {
|
||||
background-image: url(../img/icons/General_1x.png);
|
||||
}
|
||||
.im_emoji_btn:hover .icon-emoji {
|
||||
.composer_emoji_insert_btn:hover .icon-emoji {
|
||||
opacity: 1;
|
||||
}
|
||||
.im_emoji_btn:active .icon-emoji,
|
||||
.im_emoji_btn.on .icon-emoji {
|
||||
.composer_emoji_insert_btn:active .icon-emoji,
|
||||
.composer_emoji_insert_btn.composer_emoji_insert_btn_on .icon-emoji {
|
||||
background-position: -9px -367px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.im_send_field_wrap {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.emoji-wysiwyg-editor,
|
||||
.form-control.im_message_field {
|
||||
.composer_rich_textarea,
|
||||
.composer_textarea {
|
||||
border-radius: 0;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
@ -988,8 +999,8 @@ a.im_panel_peer_photo .peer_initials {
|
||||
line-height: 20px;
|
||||
height: auto;
|
||||
}
|
||||
.emoji-wysiwyg-editor:focus,
|
||||
.form-control.im_message_field:focus {
|
||||
.composer_rich_textarea:focus,
|
||||
.composer_textarea:focus {
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
@ -1014,7 +1025,7 @@ a.im_panel_peer_photo .peer_initials {
|
||||
height: 17px;
|
||||
vertical-align: top;
|
||||
background: url(../img/icons/General.png) no-repeat -11px -455px;
|
||||
background-size: 40px 678px;
|
||||
background-size: 40px 778px;
|
||||
opacity: 0.8;
|
||||
margin: 0;
|
||||
}
|
||||
@ -1050,7 +1061,7 @@ a.im_panel_peer_photo .peer_initials {
|
||||
height: 18px;
|
||||
vertical-align: top;
|
||||
background: url(../img/icons/General.png) no-repeat -10px -399px;
|
||||
background-size: 40px 678px;
|
||||
background-size: 40px 778px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
.is_1x .icon-camera {
|
||||
|
@ -1105,7 +1105,7 @@ a.mobile_modal_action .tg_checkbox_label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.im_emoji_btn {
|
||||
.composer_emoji_insert_btn {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
@ -1127,10 +1127,10 @@ a.mobile_modal_action .tg_checkbox_label {
|
||||
.is_1x .icon-emoji {
|
||||
background-image: url(../img/icons/IconsetW_1x.png);
|
||||
}
|
||||
.im_emoji_btn:active .icon-emoji,
|
||||
.is_1x .im_emoji_btn:active .icon-emoji,
|
||||
.im_emoji_btn.on .icon-emoji,
|
||||
.is_1x .im_emoji_btn.on .icon-emoji {
|
||||
.composer_emoji_insert_btn:active .icon-emoji,
|
||||
.is_1x .composer_emoji_insert_btn:active .icon-emoji,
|
||||
.composer_emoji_insert_btn.on .icon-emoji,
|
||||
.is_1x .composer_emoji_insert_btn.on .icon-emoji {
|
||||
background-position: -10px -803px;
|
||||
}
|
||||
|
||||
@ -1141,21 +1141,21 @@ a.mobile_modal_action .tg_checkbox_label {
|
||||
.im_send_field_wrap .form-control {
|
||||
border-radius: 4px;
|
||||
}
|
||||
.emoji-wysiwyg-editor {
|
||||
.composer_rich_textarea {
|
||||
min-height: 18px;
|
||||
max-height: 136px;
|
||||
margin-bottom: 0;
|
||||
font-size: 15px;
|
||||
}
|
||||
.emoji-wysiwyg-editor:empty {
|
||||
.composer_rich_textarea:empty {
|
||||
background: #f1f1f1;
|
||||
border-color: #f1f1f1;
|
||||
}
|
||||
.emoji-wysiwyg-editor:empty:before {
|
||||
.composer_rich_textarea:empty:before {
|
||||
color: #999;
|
||||
}
|
||||
.emoji-wysiwyg-editor:active,
|
||||
.emoji-wysiwyg-editor:focus {
|
||||
.composer_rich_textarea:active,
|
||||
.composer_rich_textarea:focus {
|
||||
box-shadow: none;
|
||||
outline: 0;
|
||||
background: #FFF;
|
||||
@ -1164,17 +1164,33 @@ a.mobile_modal_action .tg_checkbox_label {
|
||||
}
|
||||
|
||||
|
||||
.emoji-menu {
|
||||
margin-left: -20px;
|
||||
margin-top: -202px;
|
||||
.composer_emoji_tooltip {
|
||||
margin-left: 10px;
|
||||
margin-top: -175px;
|
||||
width: 262px;
|
||||
}
|
||||
.emoji-menu .emoji-items-wrap {
|
||||
.composer_emoji_tooltip .composer_emoji_tooltip_content {
|
||||
height: 106px;
|
||||
}
|
||||
.emoji-menu .emoji-items a {
|
||||
.composer_emoji_tooltip .composer_emoji_tooltip_content .composer_emoji_btn {
|
||||
padding: 5px;
|
||||
}
|
||||
.icon-tooltip-tail {
|
||||
display: none;
|
||||
}
|
||||
.composer_emoji_tooltip_tab {
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.composer_sticker_btn {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
padding: 3px;
|
||||
}
|
||||
.composer_sticker_image {
|
||||
max-width: 64px;
|
||||
max-height: 64px;
|
||||
}
|
||||
|
||||
|
||||
.contacts_modal_search {
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 9.8 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 4.9 KiB |
@ -48,7 +48,6 @@
|
||||
<script type="text/javascript" src="js/lib/config.js"></script>
|
||||
<script type="text/javascript" src="js/init.js"></script>
|
||||
<script type="text/javascript" src="vendor/jquery.nanoscroller/nanoscroller.js"></script>
|
||||
<script type="text/javascript" src="vendor/jquery.emojiarea/jquery.emojiarea.js"></script>
|
||||
|
||||
<script type="text/javascript" src="vendor/angular/angular.js"></script>
|
||||
<script type="text/javascript" src="vendor/angular/angular-route.js"></script>
|
||||
@ -83,6 +82,7 @@
|
||||
<script type="text/javascript" src="js/templates.js"></script>
|
||||
PRODUCTION_ONLY_END-->
|
||||
|
||||
<script type="text/javascript" src="js/message_composer.js"></script>
|
||||
<script type="text/javascript" src="js/directives.js"></script>
|
||||
<script type="text/javascript" src="js/directives_mobile.js"></script>
|
||||
<!-- endbuild -->
|
||||
|
@ -27,25 +27,25 @@ angular.module('myApp', [
|
||||
]).
|
||||
config(['$locationProvider', '$routeProvider', '$compileProvider', 'StorageProvider', function($locationProvider, $routeProvider, $compileProvider, StorageProvider) {
|
||||
|
||||
var icons = {}, reverseIcons = {}, i, j, hex, name, dataItem, row, column, totalColumns;
|
||||
// var icons = {}, reverseIcons = {}, i, j, hex, name, dataItem, row, column, totalColumns;
|
||||
|
||||
for (j = 0; j < Config.EmojiCategories.length; j++) {
|
||||
totalColumns = Config.EmojiCategorySpritesheetDimens[j][1];
|
||||
for (i = 0; i < Config.EmojiCategories[j].length; i++) {
|
||||
dataItem = Config.Emoji[Config.EmojiCategories[j][i]];
|
||||
name = dataItem[1][0];
|
||||
row = Math.floor(i / totalColumns);
|
||||
column = (i % totalColumns);
|
||||
icons[':' + name + ':'] = [j, row, column, ':'+name+':'];
|
||||
reverseIcons[name] = dataItem[0];
|
||||
}
|
||||
}
|
||||
// for (j = 0; j < Config.EmojiCategories.length; j++) {
|
||||
// totalColumns = Config.EmojiCategorySpritesheetDimens[j][1];
|
||||
// for (i = 0; i < Config.EmojiCategories[j].length; i++) {
|
||||
// dataItem = Config.Emoji[Config.EmojiCategories[j][i]];
|
||||
// name = dataItem[1][0];
|
||||
// row = Math.floor(i / totalColumns);
|
||||
// column = (i % totalColumns);
|
||||
// icons[':' + name + ':'] = [j, row, column, ':'+name+':'];
|
||||
// reverseIcons[name] = dataItem[0];
|
||||
// }
|
||||
// }
|
||||
|
||||
$.emojiarea.spritesheetPath = 'img/emojisprite_!.png';
|
||||
$.emojiarea.spritesheetDimens = Config.EmojiCategorySpritesheetDimens;
|
||||
$.emojiarea.iconSize = 20;
|
||||
$.emojiarea.icons = icons;
|
||||
$.emojiarea.reverseIcons = reverseIcons;
|
||||
// $.emojiarea.spritesheetPath = 'img/emojisprite_!.png';
|
||||
// $.emojiarea.spritesheetDimens = Config.EmojiCategorySpritesheetDimens;
|
||||
// $.emojiarea.iconSize = 20;
|
||||
// $.emojiarea.icons = icons;
|
||||
// $.emojiarea.reverseIcons = reverseIcons;
|
||||
|
||||
$compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|file|blob|filesystem|chrome-extension|app):|data:image\//);
|
||||
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|file|mailto|blob|filesystem|chrome-extension|app):|data:image\//);
|
||||
|
@ -316,7 +316,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
LayoutSwitchService.start();
|
||||
})
|
||||
|
||||
.controller('AppIMController', function ($scope, $location, $routeParams, $modal, $rootScope, $modalStack, MtpApiManager, AppUsersManager, AppChatsManager, AppPeersManager, ContactsSelectService, ChangelogNotifyService, ErrorService, AppRuntimeManager, HttpsMigrateService, LayoutSwitchService, LocationParamsService) {
|
||||
.controller('AppIMController', function ($scope, $location, $routeParams, $modal, $rootScope, $modalStack, MtpApiManager, AppUsersManager, AppChatsManager, AppPeersManager, ContactsSelectService, ChangelogNotifyService, ErrorService, AppRuntimeManager, HttpsMigrateService, LayoutSwitchService, LocationParamsService, AppStickersManager) {
|
||||
|
||||
$scope.$on('$routeUpdate', updateCurDialog);
|
||||
|
||||
@ -496,6 +496,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
HttpsMigrateService.start();
|
||||
LayoutSwitchService.start();
|
||||
LocationParamsService.start();
|
||||
AppStickersManager.start();
|
||||
})
|
||||
|
||||
.controller('AppImDialogsController', function ($scope, $location, $q, $timeout, $routeParams, MtpApiManager, AppUsersManager, AppChatsManager, AppMessagesManager, AppPeersManager, PhonebookContactsService, ErrorService, AppRuntimeManager) {
|
||||
@ -1454,7 +1455,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
$scope.$on('user_update', angular.noop);
|
||||
})
|
||||
|
||||
.controller('AppImSendController', function ($scope, $timeout, MtpApiManager, Storage, AppPeersManager, AppMessagesManager, ApiUpdatesManager, MtpApiFileManager) {
|
||||
.controller('AppImSendController', function ($scope, $timeout, MtpApiManager, Storage, AppPeersManager, AppDocsManager, AppMessagesManager, ApiUpdatesManager, MtpApiFileManager) {
|
||||
|
||||
$scope.$watch('curDialog.peer', resetDraft);
|
||||
$scope.$on('user_update', angular.noop);
|
||||
@ -1463,6 +1464,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
$scope.draftMessage = {text: '', send: sendMessage};
|
||||
$scope.$watch('draftMessage.text', onMessageChange);
|
||||
$scope.$watch('draftMessage.files', onFilesSelected);
|
||||
$scope.$watch('draftMessage.sticker', onStickerSelected);
|
||||
|
||||
function sendMessage (e) {
|
||||
$scope.$broadcast('ui_message_before_send');
|
||||
@ -1471,10 +1473,10 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
var text = $scope.draftMessage.text;
|
||||
|
||||
if (angular.isString(text) && text.length > 0) {
|
||||
text = text.replace(/:([a-z0-9\-\+\*_]+?):/gi, function (all, name) {
|
||||
var utfChar = $.emojiarea.reverseIcons[name];
|
||||
if (utfChar !== undefined) {
|
||||
return utfChar;
|
||||
text = text.replace(/:([a-z0-9\-\+\*_]+?):/gi, function (all, shortcut) {
|
||||
var emojiCode = EmojiHelper.shortcuts[shortcut];
|
||||
if (emojiCode !== undefined) {
|
||||
return EmojiHelper.emojis[emojiCode][0];
|
||||
}
|
||||
return all;
|
||||
});
|
||||
@ -1529,10 +1531,10 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
var backupDraftObj = {};
|
||||
backupDraftObj['draft' + $scope.curDialog.peerID] = newVal;
|
||||
Storage.set(backupDraftObj);
|
||||
// console.log('draft save', backupDraftObj);
|
||||
// console.log(dT(), 'draft save', backupDraftObj);
|
||||
} else {
|
||||
Storage.remove('draft' + $scope.curDialog.peerID);
|
||||
// console.log('draft delete', 'draft' + $scope.curDialog.peerID);
|
||||
// console.log(dT(), 'draft delete', 'draft' + $scope.curDialog.peerID);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1555,6 +1557,28 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
$scope.$broadcast('ui_message_send');
|
||||
}
|
||||
}
|
||||
|
||||
function onStickerSelected (newVal) {
|
||||
if (!newVal) {
|
||||
return;
|
||||
}
|
||||
|
||||
var doc = AppDocsManager.getDoc(newVal);
|
||||
if (doc.id && doc.access_hash) {
|
||||
console.log('sticker', doc);
|
||||
var inputMedia = {
|
||||
_: 'inputMediaDocument',
|
||||
id: {
|
||||
_: 'inputDocument',
|
||||
id: doc.id,
|
||||
access_hash: doc.access_hash
|
||||
}
|
||||
}
|
||||
AppMessagesManager.sendOther($scope.curDialog.peerID, inputMedia);
|
||||
$scope.$broadcast('ui_message_send');
|
||||
}
|
||||
delete $scope.draftMessage.sticker;
|
||||
}
|
||||
})
|
||||
|
||||
.controller('AppLangSelectController', function ($scope, _, Storage, ErrorService, AppRuntimeManager) {
|
||||
@ -3017,7 +3041,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
|
||||
})
|
||||
|
||||
.controller('CountrySelectModalController', function ($scope, $modalInstance, $rootScope, SearchIndexManager, _) {
|
||||
.controller('CountrySelectModalController', function ($scope, $modalInstance, $rootScope, _) {
|
||||
|
||||
$scope.search = {};
|
||||
$scope.slice = {limit: 20, limitDelta: 20}
|
||||
@ -3060,7 +3084,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
})
|
||||
|
||||
|
||||
.controller('PhonebookModalController', function ($scope, $modalInstance, $rootScope, AppUsersManager, PhonebookContactsService, SearchIndexManager, ErrorService) {
|
||||
.controller('PhonebookModalController', function ($scope, $modalInstance, $rootScope, AppUsersManager, PhonebookContactsService, ErrorService) {
|
||||
|
||||
$scope.search = {};
|
||||
$scope.phonebook = [];
|
||||
|
@ -1061,7 +1061,7 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
|
||||
})
|
||||
|
||||
.directive('mySendForm', function ($timeout, $modalStack, $http, $interpolate, Storage, ErrorService) {
|
||||
.directive('mySendForm', function ($timeout, $modalStack, $http, $interpolate, Storage, AppStickersManager, ErrorService) {
|
||||
|
||||
return {
|
||||
link: link,
|
||||
@ -1071,139 +1071,107 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
};
|
||||
|
||||
function link ($scope, element, attrs) {
|
||||
var messageField = $('textarea', element)[0],
|
||||
fileSelects = $('input', element),
|
||||
dropbox = $('.im_send_dropbox_wrap', element)[0],
|
||||
emojiButton = $('.im_emoji_btn', element)[0],
|
||||
emojiQuickSelect = !Config.Mobile ? $('.im_emoji_quick_select_area', element)[0] : false,
|
||||
editorElement = messageField,
|
||||
dragStarted, dragTimeout,
|
||||
emojiArea = $(messageField).emojiarea({button: emojiButton, norealTime: true, quickSelect: emojiQuickSelect}),
|
||||
emojiMenu = $('.emoji-menu', element)[0],
|
||||
submitBtn = $('.im_submit', element)[0],
|
||||
richTextarea = $('.emoji-wysiwyg-editor', element)[0];
|
||||
|
||||
if (richTextarea) {
|
||||
editorElement = richTextarea;
|
||||
$(richTextarea).addClass('form-control');
|
||||
$(richTextarea).attr('placeholder', $interpolate($(messageField).attr('placeholder'))($scope));
|
||||
var messageField = $('textarea', element)[0];
|
||||
var emojiButton = $('.composer_emoji_insert_btn', element)[0];
|
||||
var emojiPanel = $('.composer_emoji_panel', element)[0];
|
||||
var fileSelects = $('input', element);
|
||||
var dropbox = $('.im_send_dropbox_wrap', element)[0];
|
||||
var messageFieldWrap = $('.im_send_field_wrap', element)[0];
|
||||
var dragStarted, dragTimeout;
|
||||
var submitBtn = $('.im_submit', element)[0];
|
||||
|
||||
var updatePromise;
|
||||
$(richTextarea)
|
||||
.on('DOMNodeInserted', onPastedImageEvent)
|
||||
.on('keyup', function (e) {
|
||||
updateHeight();
|
||||
|
||||
if (!sendAwaiting) {
|
||||
$scope.$apply(function () {
|
||||
$scope.draftMessage.text = richTextarea.textContent;
|
||||
});
|
||||
}
|
||||
|
||||
$timeout.cancel(updatePromise);
|
||||
updatePromise = $timeout(updateValue, 1000);
|
||||
new EmojiTooltip(emojiButton, {
|
||||
getStickers: function (callback) {
|
||||
AppStickersManager.getStickers().then(function () {
|
||||
AppStickersManager.getStickersImages().then(function (stickersData) {
|
||||
callback(stickersData);
|
||||
});
|
||||
});
|
||||
},
|
||||
onEmojiSelected: function (code) {
|
||||
$scope.$apply(function () {
|
||||
composer.onEmojiSelected(code);
|
||||
})
|
||||
},
|
||||
onStickerSelected: function (docID) {
|
||||
$scope.$apply(function () {
|
||||
$scope.draftMessage.sticker = docID;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var composerEmojiPanel;
|
||||
if (emojiPanel) {
|
||||
composerEmojiPanel = new EmojiPanel(emojiPanel, {
|
||||
onEmojiSelected: function (code) {
|
||||
composer.onEmojiSelected(code);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Head is sometimes slower
|
||||
$timeout(function () {
|
||||
fileSelects
|
||||
.on('change', function () {
|
||||
var self = this;
|
||||
$scope.$apply(function () {
|
||||
$scope.draftMessage.files = Array.prototype.slice.call(self.files);
|
||||
$scope.draftMessage.isMedia = $(self).hasClass('im_media_attach_input') || Config.Mobile;
|
||||
setTimeout(function () {
|
||||
try {
|
||||
self.value = '';
|
||||
} catch (e) {};
|
||||
}, 1000);
|
||||
});
|
||||
});
|
||||
}, 1000);
|
||||
var composer = new MessageComposer(messageField, {
|
||||
onTyping: function () {
|
||||
$scope.$emit('ui_typing');
|
||||
},
|
||||
getSendOnEnter: function () {
|
||||
return sendOnEnter;
|
||||
},
|
||||
onMessageSubmit: onMessageSubmit,
|
||||
onFilesPaste: onFilesPaste
|
||||
});
|
||||
|
||||
var sendOnEnter = true,
|
||||
updateSendSettings = function () {
|
||||
Storage.get('send_ctrlenter').then(function (sendOnCtrl) {
|
||||
sendOnEnter = !sendOnCtrl;
|
||||
});
|
||||
};
|
||||
var richTextarea = composer.richTextareaEl[0];
|
||||
if (richTextarea) {
|
||||
$(richTextarea)
|
||||
.attr('placeholder', $interpolate($(messageField).attr('placeholder'))($scope))
|
||||
.on('keydown keyup', updateHeight);
|
||||
}
|
||||
|
||||
fileSelects.on('change', function () {
|
||||
var self = this;
|
||||
$scope.$apply(function () {
|
||||
$scope.draftMessage.files = Array.prototype.slice.call(self.files);
|
||||
$scope.draftMessage.isMedia = $(self).hasClass('im_media_attach_input') || Config.Mobile;
|
||||
setTimeout(function () {
|
||||
try {
|
||||
self.value = '';
|
||||
} catch (e) {};
|
||||
}, 1000);
|
||||
});
|
||||
});
|
||||
|
||||
var sendOnEnter = true;
|
||||
function updateSendSettings () {
|
||||
Storage.get('send_ctrlenter').then(function (sendOnCtrl) {
|
||||
sendOnEnter = !sendOnCtrl;
|
||||
});
|
||||
};
|
||||
$scope.$on('settings_changed', updateSendSettings);
|
||||
updateSendSettings();
|
||||
|
||||
$(editorElement).on('keydown', function (e) {
|
||||
if (richTextarea) {
|
||||
updateHeight();
|
||||
}
|
||||
$(submitBtn).on('mousedown touchstart', onMessageSubmit);
|
||||
|
||||
if (e.keyCode == 13) {
|
||||
var submit = false;
|
||||
if (sendOnEnter && !e.shiftKey) {
|
||||
submit = true;
|
||||
} else if (!sendOnEnter && (e.ctrlKey || e.metaKey)) {
|
||||
submit = true;
|
||||
function onMessageSubmit (e) {
|
||||
$scope.$apply(function () {
|
||||
updateValue();
|
||||
$scope.draftMessage.send();
|
||||
composer.resetTyping();
|
||||
if (composerEmojiPanel) {
|
||||
composerEmojiPanel.update();
|
||||
}
|
||||
|
||||
if (submit) {
|
||||
$timeout.cancel(updatePromise);
|
||||
updateValue();
|
||||
$scope.draftMessage.send();
|
||||
$(element).trigger('message_send');
|
||||
resetTyping();
|
||||
return cancelEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
$(submitBtn).on('mousedown touchstart', function (e) {
|
||||
$timeout.cancel(updatePromise);
|
||||
updateValue();
|
||||
$scope.draftMessage.send();
|
||||
$(element).trigger('message_send');
|
||||
resetTyping();
|
||||
});
|
||||
return cancelEvent(e);
|
||||
});
|
||||
|
||||
var lastTyping = 0,
|
||||
lastLength;
|
||||
$(editorElement).on('keyup', function (e) {
|
||||
var now = tsNow(),
|
||||
length = (editorElement[richTextarea ? 'textContent' : 'value']).length;
|
||||
|
||||
|
||||
if (now - lastTyping > 5000 && length != lastLength) {
|
||||
lastTyping = now;
|
||||
lastLength = length;
|
||||
$scope.$emit('ui_typing');
|
||||
}
|
||||
});
|
||||
|
||||
function resetTyping () {
|
||||
lastTyping = 0;
|
||||
lastLength = 0;
|
||||
};
|
||||
|
||||
function updateRichTextarea () {
|
||||
if (richTextarea) {
|
||||
$timeout.cancel(updatePromise);
|
||||
var html = $('<div>').text($scope.draftMessage.text || '').html();
|
||||
html = html.replace(/\n/g, '<br/>');
|
||||
$(richTextarea).html(html);
|
||||
lastLength = html.length;
|
||||
updateHeight();
|
||||
}
|
||||
}
|
||||
|
||||
function updateValue () {
|
||||
if (richTextarea) {
|
||||
$(richTextarea).trigger('change');
|
||||
composer.onChange();
|
||||
updateHeight();
|
||||
}
|
||||
}
|
||||
|
||||
var height = richTextarea.offsetHeight;
|
||||
var height = richTextarea && richTextarea.offsetHeight;
|
||||
function updateHeight () {
|
||||
var newHeight = richTextarea.offsetHeight;
|
||||
if (height != newHeight) {
|
||||
@ -1214,7 +1182,7 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
|
||||
function onKeyDown(e) {
|
||||
if (e.keyCode == 9 && !e.shiftKey && !e.ctrlKey && !e.metaKey && !$modalStack.getTop()) { // TAB
|
||||
editorElement.focus();
|
||||
composer.focus();
|
||||
return cancelEvent(e);
|
||||
}
|
||||
}
|
||||
@ -1229,13 +1197,18 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
$scope.$on('ui_history_change', focusField);
|
||||
}
|
||||
|
||||
$scope.$on('ui_peer_change', resetTyping);
|
||||
$scope.$on('ui_peer_draft', updateRichTextarea);
|
||||
$scope.$on('ui_peer_change', composer.resetTyping.bind(composer));
|
||||
$scope.$on('ui_peer_draft', function () {
|
||||
if (richTextarea) {
|
||||
composer.setValue($scope.draftMessage.text || '');
|
||||
updateHeight();
|
||||
}
|
||||
composer.focus();
|
||||
});
|
||||
|
||||
var sendAwaiting = false;
|
||||
$scope.$on('ui_message_before_send', function () {
|
||||
sendAwaiting = true;
|
||||
$timeout.cancel(updatePromise);
|
||||
updateValue();
|
||||
});
|
||||
$scope.$on('ui_message_send', function () {
|
||||
@ -1243,35 +1216,17 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
focusField();
|
||||
});
|
||||
|
||||
|
||||
function focusField () {
|
||||
onContentLoaded(function () {
|
||||
editorElement.focus();
|
||||
composer.focus();
|
||||
});
|
||||
}
|
||||
|
||||
function onPastedImageEvent (e) {
|
||||
var element = (e.originalEvent || e).target,
|
||||
src = (element || {}).src || '',
|
||||
remove = false;
|
||||
|
||||
if (src.substr(0, 5) == 'data:') {
|
||||
remove = true;
|
||||
var blob = dataUrlToBlob(src);
|
||||
ErrorService.confirm({type: 'FILE_CLIPBOARD_PASTE'}).then(function () {
|
||||
$scope.draftMessage.files = [blob];
|
||||
$scope.draftMessage.isMedia = true;
|
||||
});
|
||||
setZeroTimeout(function () {
|
||||
element.parentNode.removeChild(element);
|
||||
})
|
||||
}
|
||||
else if (src && !src.match(/img\/blank\.gif/)) {
|
||||
var replacementNode = document.createTextNode(' ' + src + ' ');
|
||||
setTimeout(function () {
|
||||
element.parentNode.replaceChild(replacementNode, element);
|
||||
}, 100);
|
||||
}
|
||||
function onFilesPaste (blobs) {
|
||||
ErrorService.confirm({type: 'FILE_CLIPBOARD_PASTE'}).then(function () {
|
||||
$scope.draftMessage.files = blobs;
|
||||
$scope.draftMessage.isMedia = true;
|
||||
});
|
||||
};
|
||||
|
||||
function onPasteEvent (e) {
|
||||
@ -1312,7 +1267,7 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
if (e.type == 'dragenter' || e.type == 'dragover') {
|
||||
if (dragStateChanged) {
|
||||
$(dropbox)
|
||||
.css({height: editorElement.offsetHeight + 2, width: editorElement.offsetWidth})
|
||||
.css({height: messageFieldWrap.offsetHeight + 2, width: messageFieldWrap.offsetWidth})
|
||||
.show();
|
||||
}
|
||||
} else {
|
||||
@ -1335,15 +1290,11 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
|
||||
|
||||
$scope.$on('$destroy', function cleanup() {
|
||||
$('body').off('dragenter dragleave dragover drop', onDragDropEvent);
|
||||
$(document).off('paste', onPasteEvent);
|
||||
$(document).off('keydown', onKeyDown);
|
||||
$(submitBtn).off('mousedown')
|
||||
$('body').off('dragenter dragleave dragover drop', onDragDropEvent);
|
||||
$(submitBtn).off('mousedown touchstart');
|
||||
fileSelects.off('change');
|
||||
if (richTextarea) {
|
||||
$(richTextarea).off('DOMNodeInserted keyup', onPastedImageEvent);
|
||||
}
|
||||
$(editorElement).off('keydown');
|
||||
});
|
||||
|
||||
if (!Config.Navigator.touch) {
|
||||
@ -2587,4 +2538,4 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
}
|
||||
};
|
||||
|
||||
})
|
||||
})
|
@ -734,104 +734,6 @@ angular.module('izhukov.utils', [])
|
||||
};
|
||||
})
|
||||
|
||||
.service('SearchIndexManager', function () {
|
||||
var badCharsRe = /[`~!@#$%^&*()\-_=+\[\]\\|{}'";:\/?.>,<\s]+/g,
|
||||
trimRe = /^\s+|\s$/g;
|
||||
|
||||
return {
|
||||
createIndex: createIndex,
|
||||
indexObject: indexObject,
|
||||
cleanSearchText: cleanSearchText,
|
||||
search: search
|
||||
};
|
||||
|
||||
function createIndex () {
|
||||
return {
|
||||
shortIndexes: {},
|
||||
fullTexts: {}
|
||||
}
|
||||
}
|
||||
|
||||
function cleanSearchText (text) {
|
||||
text = text.replace(badCharsRe, ' ').replace(trimRe, '');
|
||||
text = text.replace(/[^A-Za-z0-9]/g, function (ch) {
|
||||
return Config.LatinizeMap[ch] || ch;
|
||||
});
|
||||
text = text.toLowerCase();
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
function indexObject (id, searchText, searchIndex) {
|
||||
if (searchIndex.fullTexts[id] !== undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
searchText = cleanSearchText(searchText);
|
||||
|
||||
if (!searchText.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var shortIndexes = searchIndex.shortIndexes;
|
||||
|
||||
searchIndex.fullTexts[id] = searchText;
|
||||
|
||||
angular.forEach(searchText.split(' '), function(searchWord) {
|
||||
var len = Math.min(searchWord.length, 3),
|
||||
wordPart, i;
|
||||
for (i = 1; i <= len; i++) {
|
||||
wordPart = searchWord.substr(0, i);
|
||||
if (shortIndexes[wordPart] === undefined) {
|
||||
shortIndexes[wordPart] = [id];
|
||||
} else {
|
||||
shortIndexes[wordPart].push(id);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function search (query, searchIndex) {
|
||||
var shortIndexes = searchIndex.shortIndexes,
|
||||
fullTexts = searchIndex.fullTexts;
|
||||
|
||||
query = cleanSearchText(query);
|
||||
|
||||
var queryWords = query.split(' '),
|
||||
foundObjs = false,
|
||||
newFoundObjs, i, j, searchText, found;
|
||||
|
||||
for (i = 0; i < queryWords.length; i++) {
|
||||
newFoundObjs = shortIndexes[queryWords[i].substr(0, 3)];
|
||||
if (!newFoundObjs) {
|
||||
foundObjs = [];
|
||||
break;
|
||||
}
|
||||
if (foundObjs === false || foundObjs.length > newFoundObjs.length) {
|
||||
foundObjs = newFoundObjs;
|
||||
}
|
||||
}
|
||||
|
||||
newFoundObjs = {};
|
||||
|
||||
for (j = 0; j < foundObjs.length; j++) {
|
||||
found = true;
|
||||
searchText = fullTexts[foundObjs[j]];
|
||||
for (i = 0; i < queryWords.length; i++) {
|
||||
if (searchText.indexOf(queryWords[i]) == -1) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
newFoundObjs[foundObjs[j]] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return newFoundObjs;
|
||||
}
|
||||
})
|
||||
|
||||
.service('ExternalResourcesManager', function ($q, $http) {
|
||||
var urlPromises = {};
|
||||
|
||||
|
@ -156,8 +156,6 @@ peerNotifyEventsAll#6d1ded88 = PeerNotifyEvents;
|
||||
peerNotifySettingsEmpty#70a68512 = PeerNotifySettings;
|
||||
peerNotifySettings#8d5e11ee mute_until:int sound:string show_previews:Bool events_mask:int = PeerNotifySettings;
|
||||
|
||||
globalPrivacySettings#40f5c53a no_suggestions:Bool hide_contacts:Bool hide_located:Bool hide_last_visit:Bool = GlobalPrivacySettings;
|
||||
|
||||
wallPaper#ccb03657 id:int title:string sizes:Vector<PhotoSize> color:int = WallPaper;
|
||||
|
||||
userFull#771095da user:User link:contacts.Link profile_photo:Photo notify_settings:PeerNotifySettings blocked:Bool real_first_name:string real_last_name:string = UserFull;
|
||||
@ -209,8 +207,6 @@ messages.statedMessage#d07ae726 message:Message chats:Vector<Chat> users:Vector<
|
||||
|
||||
messages.sentMessage#d1f4d35c id:int date:int pts:int seq:int = messages.SentMessage;
|
||||
|
||||
messages.chat#40e9002a chat:Chat users:Vector<User> = messages.Chat;
|
||||
|
||||
messages.chats#8150cbd8 chats:Vector<Chat> users:Vector<User> = messages.Chats;
|
||||
|
||||
messages.chatFull#e5d7d19c full_chat:ChatFull chats:Vector<Chat> users:Vector<User> = messages.ChatFull;
|
||||
@ -221,6 +217,7 @@ inputMessagesFilterEmpty#57e2f66c = MessagesFilter;
|
||||
inputMessagesFilterPhotos#9609a51c = MessagesFilter;
|
||||
inputMessagesFilterVideo#9fc00e65 = MessagesFilter;
|
||||
inputMessagesFilterPhotoVideo#56e9f0e4 = MessagesFilter;
|
||||
inputMessagesFilterPhotoVideoDocuments#d95e73bb = MessagesFilter;
|
||||
inputMessagesFilterDocument#9eddf188 = MessagesFilter;
|
||||
inputMessagesFilterAudio#cfc87522 = MessagesFilter;
|
||||
|
||||
@ -228,7 +225,6 @@ updateNewMessage#13abdb3 message:Message pts:int = Update;
|
||||
updateMessageID#4e90bfd6 id:int random_id:long = Update;
|
||||
updateReadMessages#c6649e31 messages:Vector<int> pts:int = Update;
|
||||
updateDeleteMessages#a92bfe26 messages:Vector<int> pts:int = Update;
|
||||
updateRestoreMessages#d15de04d messages:Vector<int> pts:int = Update;
|
||||
updateUserTyping#5c486927 user_id:int action:SendMessageAction = Update;
|
||||
updateChatUserTyping#9a65ea1f chat_id:int user_id:int action:SendMessageAction = Update;
|
||||
updateChatParticipants#7761198 participants:ChatParticipants = Update;
|
||||
@ -237,7 +233,6 @@ updateUserName#a7332b73 user_id:int first_name:string last_name:string username:
|
||||
updateUserPhoto#95313b0c user_id:int date:int photo:UserProfilePhoto previous:Bool = Update;
|
||||
updateContactRegistered#2575bbb9 user_id:int date:int = Update;
|
||||
updateContactLink#51a48a9a user_id:int my_link:contacts.MyLink foreign_link:contacts.ForeignLink = Update;
|
||||
updateActivation#6f690963 user_id:int = Update;
|
||||
updateNewAuthorization#8f06529a auth_key_id:long date:int device:string location:string = Update;
|
||||
|
||||
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
|
||||
@ -438,6 +433,11 @@ documentAttributeFilename#15590068 file_name:string = DocumentAttribute;
|
||||
messages.stickersNotModified#f1749a22 = messages.Stickers;
|
||||
messages.stickers#8a8ecd32 hash:string stickers:Vector<Document> = messages.Stickers;
|
||||
|
||||
stickerPack#12b299d4 emoticon:string documents:Vector<long> = StickerPack;
|
||||
|
||||
messages.allStickersNotModified#e86602c3 = messages.AllStickers;
|
||||
messages.allStickers#dcef3102 hash:string packs:Vector<StickerPack> documents:Vector<Document> = messages.AllStickers;
|
||||
|
||||
---functions---
|
||||
|
||||
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
||||
@ -487,7 +487,6 @@ messages.search#7e9f2ab peer:InputPeer q:string filter:MessagesFilter min_date:i
|
||||
messages.readHistory#eed884c6 peer:InputPeer max_id:int offset:int read_contents:Bool = messages.AffectedHistory;
|
||||
messages.deleteHistory#f4f8fb61 peer:InputPeer offset:int = messages.AffectedHistory;
|
||||
messages.deleteMessages#14f2dd0a id:Vector<int> = Vector<int>;
|
||||
messages.restoreMessages#395f9d7e id:Vector<int> = Vector<int>;
|
||||
messages.receivedMessages#28abcb68 max_id:int = Vector<int>;
|
||||
messages.setTyping#a3825e50 peer:InputPeer action:SendMessageAction = Bool;
|
||||
messages.sendMessage#4cde0aab peer:InputPeer message:string random_id:long = messages.SentMessage;
|
||||
@ -578,4 +577,5 @@ account.setPassword#dd2a4d8f current_password_hash:bytes new_salt:bytes new_pass
|
||||
|
||||
auth.checkPassword#a63011e password_hash:bytes = auth.Authorization;
|
||||
|
||||
messages.getStickers#ae22e045 emoticon:string hash:string = messages.Stickers;
|
||||
messages.getStickers#ae22e045 emoticon:string hash:string = messages.Stickers;
|
||||
messages.getAllStickers#aa3bc868 hash:string = messages.AllStickers;
|
@ -58,9 +58,173 @@ function onCtrlEnter (textarea, cb) {
|
||||
});
|
||||
}
|
||||
|
||||
function setFieldSelection(field, from, to) {
|
||||
field = $(field)[0];
|
||||
try {
|
||||
field.focus();
|
||||
if (from === undefined || from === false) {
|
||||
from = field.value.length;
|
||||
}
|
||||
if (to === undefined || to === false) {
|
||||
to = from;
|
||||
}
|
||||
if (field.createTextRange) {
|
||||
var range = field.createTextRange();
|
||||
range.collapse(true);
|
||||
range.moveEnd('character', to);
|
||||
range.moveStart('character', from);
|
||||
range.select();
|
||||
}
|
||||
else if (field.setSelectionRange) {
|
||||
field.setSelectionRange(from, to);
|
||||
}
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
function getFieldSelection (field) {
|
||||
if (field.selectionStart) {
|
||||
return field.selectionStart;
|
||||
}
|
||||
else if (!document.selection) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var c = "\001",
|
||||
sel = document.selection.createRange(),
|
||||
txt = sel.text,
|
||||
dup = sel.duplicate(),
|
||||
len = 0;
|
||||
|
||||
try {
|
||||
dup.moveToElementText(field);
|
||||
} catch(e) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
sel.text = txt + c;
|
||||
len = dup.text.indexOf(c);
|
||||
sel.moveStart('character', -1);
|
||||
sel.text = '';
|
||||
|
||||
// if (browser.msie && len == -1) {
|
||||
// return field.value.length;
|
||||
// }
|
||||
return len;
|
||||
}
|
||||
|
||||
function getRichValue(field) {
|
||||
if (!field) {
|
||||
return '';
|
||||
}
|
||||
var lines = [];
|
||||
var line = [];
|
||||
|
||||
getRichElementValue(field, lines, line);
|
||||
if (line.length) {
|
||||
lines.push(line.join(''));
|
||||
}
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
function getRichValueWithCaret(field) {
|
||||
if (!field) {
|
||||
return [];
|
||||
}
|
||||
var lines = [];
|
||||
var line = [];
|
||||
|
||||
var sel = window.getSelection ? window.getSelection() : false;
|
||||
var selNode, selOffset;
|
||||
if (sel && sel.rangeCount) {
|
||||
var range = sel.getRangeAt(0);
|
||||
if (range.startContainer &&
|
||||
range.startContainer == range.endContainer &&
|
||||
range.startOffset == range.endOffset) {
|
||||
selNode = range.startContainer;
|
||||
selOffset = range.startOffset;
|
||||
}
|
||||
}
|
||||
|
||||
getRichElementValue(field, lines, line, selNode, selOffset);
|
||||
|
||||
if (line.length) {
|
||||
lines.push(line.join(''));
|
||||
}
|
||||
|
||||
var value = lines.join('\n');
|
||||
var caretPos = value.indexOf('\001');
|
||||
if (caretPos != -1) {
|
||||
value = value.substr(0, caretPos) + value.substr(caretPos + 1);
|
||||
}
|
||||
|
||||
return [value, caretPos];
|
||||
}
|
||||
|
||||
function getRichElementValue(node, lines, line, selNode, selOffset) {
|
||||
if (node.nodeType == 3) { // TEXT
|
||||
if (selNode === node) {
|
||||
var value = node.nodeValue;
|
||||
line.push(value.substr(0, selOffset) + '\001' + value.substr(selOffset));
|
||||
} else {
|
||||
line.push(node.nodeValue);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (node.nodeType != 1) { // NON-ELEMENT
|
||||
return;
|
||||
}
|
||||
var isBlock = node.tagName == 'DIV' || node.tagName == 'P';
|
||||
var curChild;
|
||||
if (isBlock && line.length || node.tagName == 'BR') {
|
||||
lines.push(line.join(''));
|
||||
line.splice(0, line.length);
|
||||
}
|
||||
else if (node.tagName == 'IMG') {
|
||||
if (node.alt) {
|
||||
line.push(node.alt);
|
||||
}
|
||||
}
|
||||
if (selNode === node) {
|
||||
line.push('\001');
|
||||
}
|
||||
var curChild = node.firstChild;
|
||||
while (curChild) {
|
||||
getRichElementValue(curChild, lines, line, selNode, selOffset);
|
||||
curChild = curChild.nextSibling;
|
||||
}
|
||||
if (isBlock && line.length) {
|
||||
lines.push(line.join(''));
|
||||
line.splice(0, line.length);
|
||||
}
|
||||
}
|
||||
|
||||
function setRichFocus(field, selectNode) {
|
||||
field.focus();
|
||||
if (window.getSelection && document.createRange) {
|
||||
var range = document.createRange();
|
||||
if (selectNode) {
|
||||
range.selectNode(selectNode);
|
||||
} else {
|
||||
range.selectNodeContents(field);
|
||||
}
|
||||
range.collapse(false);
|
||||
|
||||
var sel = window.getSelection();
|
||||
sel.removeAllRanges();
|
||||
sel.addRange(range);
|
||||
}
|
||||
else if (document.body.createTextRange !== undefined) {
|
||||
var textRange = document.body.createTextRange();
|
||||
textRange.moveToElementText(selectNode || field);
|
||||
textRange.collapse(false);
|
||||
textRange.select();
|
||||
}
|
||||
}
|
||||
|
||||
function onContentLoaded (cb) {
|
||||
setTimeout(cb, 0);
|
||||
};
|
||||
setZeroTimeout(cb);
|
||||
}
|
||||
|
||||
function tsNow (seconds) {
|
||||
var t = +new Date() + (window.tsOffset || 0);
|
||||
@ -153,27 +317,129 @@ function calcImageInBox(imageW, imageH, boxW, boxH, noZooom) {
|
||||
}
|
||||
|
||||
function versionCompare (ver1, ver2) {
|
||||
if (typeof ver1 !== 'string') {
|
||||
ver1 = '';
|
||||
}
|
||||
if (typeof ver2 !== 'string') {
|
||||
ver2 = '';
|
||||
}
|
||||
ver1 = ver1.replace(/^\s+|\s+$/g, '').split('.');
|
||||
ver2 = ver2.replace(/^\s+|\s+$/g, '').split('.');
|
||||
|
||||
var a = Math.max(ver1.length, ver2.length), i;
|
||||
|
||||
for (i = 0; i < a; i++) {
|
||||
if (ver1[i] == ver2[i]) {
|
||||
continue;
|
||||
}
|
||||
if (ver1[i] > ver2[i]) {
|
||||
return 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (typeof ver1 !== 'string') {
|
||||
ver1 = '';
|
||||
}
|
||||
if (typeof ver2 !== 'string') {
|
||||
ver2 = '';
|
||||
}
|
||||
ver1 = ver1.replace(/^\s+|\s+$/g, '').split('.');
|
||||
ver2 = ver2.replace(/^\s+|\s+$/g, '').split('.');
|
||||
|
||||
var a = Math.max(ver1.length, ver2.length), i;
|
||||
|
||||
for (i = 0; i < a; i++) {
|
||||
if (ver1[i] == ver2[i]) {
|
||||
continue;
|
||||
}
|
||||
if (ver1[i] > ver2[i]) {
|
||||
return 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
(function (global) {
|
||||
|
||||
var badCharsRe = /[`~!@#$%^&*()\-_=+\[\]\\|{}'";:\/?.>,<\s]+/g,
|
||||
trimRe = /^\s+|\s$/g;
|
||||
|
||||
function createIndex () {
|
||||
return {
|
||||
shortIndexes: {},
|
||||
fullTexts: {}
|
||||
}
|
||||
}
|
||||
|
||||
function cleanSearchText (text) {
|
||||
text = text.replace(badCharsRe, ' ').replace(trimRe, '');
|
||||
text = text.replace(/[^A-Za-z0-9]/g, function (ch) {
|
||||
return Config.LatinizeMap[ch] || ch;
|
||||
});
|
||||
text = text.toLowerCase();
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
function indexObject (id, searchText, searchIndex) {
|
||||
if (searchIndex.fullTexts[id] !== undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
searchText = cleanSearchText(searchText);
|
||||
|
||||
if (!searchText.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var shortIndexes = searchIndex.shortIndexes;
|
||||
|
||||
searchIndex.fullTexts[id] = searchText;
|
||||
|
||||
angular.forEach(searchText.split(' '), function(searchWord) {
|
||||
var len = Math.min(searchWord.length, 3),
|
||||
wordPart, i;
|
||||
for (i = 1; i <= len; i++) {
|
||||
wordPart = searchWord.substr(0, i);
|
||||
if (shortIndexes[wordPart] === undefined) {
|
||||
shortIndexes[wordPart] = [id];
|
||||
} else {
|
||||
shortIndexes[wordPart].push(id);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function search (query, searchIndex) {
|
||||
var shortIndexes = searchIndex.shortIndexes,
|
||||
fullTexts = searchIndex.fullTexts;
|
||||
|
||||
query = cleanSearchText(query);
|
||||
|
||||
var queryWords = query.split(' '),
|
||||
foundObjs = false,
|
||||
newFoundObjs, i, j, searchText, found;
|
||||
|
||||
for (i = 0; i < queryWords.length; i++) {
|
||||
newFoundObjs = shortIndexes[queryWords[i].substr(0, 3)];
|
||||
if (!newFoundObjs) {
|
||||
foundObjs = [];
|
||||
break;
|
||||
}
|
||||
if (foundObjs === false || foundObjs.length > newFoundObjs.length) {
|
||||
foundObjs = newFoundObjs;
|
||||
}
|
||||
}
|
||||
|
||||
newFoundObjs = {};
|
||||
|
||||
for (j = 0; j < foundObjs.length; j++) {
|
||||
found = true;
|
||||
searchText = fullTexts[foundObjs[j]];
|
||||
for (i = 0; i < queryWords.length; i++) {
|
||||
if (searchText.indexOf(queryWords[i]) == -1) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
newFoundObjs[foundObjs[j]] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return newFoundObjs;
|
||||
}
|
||||
|
||||
global.SearchIndexManager = {
|
||||
createIndex: createIndex,
|
||||
indexObject: indexObject,
|
||||
cleanSearchText: cleanSearchText,
|
||||
search: search
|
||||
};
|
||||
|
||||
})(window);
|
||||
|
||||
|
855
app/js/message_composer.js
Normal file
@ -0,0 +1,855 @@
|
||||
/*!
|
||||
* Webogram v0.3.9 - messaging web application for MTProto
|
||||
* https://github.com/zhukov/webogram
|
||||
* Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>
|
||||
* https://github.com/zhukov/webogram/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/* EmojiHelper */
|
||||
|
||||
(function (global, emojis, categories, spritesheets) {
|
||||
|
||||
|
||||
var emojis = {};
|
||||
var shortcuts = {};
|
||||
var spritesheetPositions = {};
|
||||
var index = false;
|
||||
|
||||
var popular = 'joy,kissing_heart,heart,heart_eyes,blush,grin,+1,relaxed,pensive,smile,sob,kiss,unamused,flushed,stuck_out_tongue_winking_eye,see_no_evil,wink,smiley,cry,stuck_out_tongue_closed_eyes,scream,rage,smirk,disappointed,sweat_smile,kissing_closed_eyes,speak_no_evil,relieved,grinning,yum,laughing,ok_hand,neutral_face,confused'.split(',');
|
||||
|
||||
var i, j, code, shortcut, emoji, row, column, totalColumns;
|
||||
var len1, len2;
|
||||
|
||||
for (i = 0, len1 = categories.length; i < len1; i++) {
|
||||
totalColumns = spritesheets[i][1];
|
||||
for (j = 0, len2 = categories[i].length; j < len2; j++) {
|
||||
code = categories[i][j];
|
||||
emoji = Config.Emoji[code];
|
||||
shortcut = emoji[1][0];
|
||||
emojis[code] = [emoji[0], shortcut];
|
||||
shortcuts[shortcut] = code;
|
||||
spritesheetPositions[code] = [i, j, Math.floor(j / totalColumns), j % totalColumns];
|
||||
}
|
||||
}
|
||||
|
||||
function getPopularEmoji (callback) {
|
||||
ConfigStorage.get('emojis_popular', function (popEmojis) {
|
||||
var result = [];
|
||||
if (popEmojis && popEmojis.length) {
|
||||
for (var i = 0, len = popEmojis.length; i < len; i++) {
|
||||
result.push({code: popEmojis[i][0], rate: popEmojis[i][1]});
|
||||
}
|
||||
callback(result);
|
||||
return;
|
||||
};
|
||||
ConfigStorage.get('emojis_recent', function (recentEmojis) {
|
||||
recentEmojis = recentEmojis || popular || [];
|
||||
var shortcut, code;
|
||||
for (var i = 0, len = recentEmojis.length; i < len; i++) {
|
||||
shortcut = recentEmojis[i];
|
||||
if (Array.isArray(shortcut)) {
|
||||
shortcut = shortcut[0];
|
||||
}
|
||||
if (shortcut.charAt(0) == ':') {
|
||||
shortcut = shortcut.substr(1, shortcut.length - 2);
|
||||
}
|
||||
if (code = shortcuts[shortcut]) {
|
||||
result.push({code: code, rate: 1});
|
||||
}
|
||||
}
|
||||
callback(result);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function pushPopularEmoji (code) {
|
||||
getPopularEmoji(function (popularEmoji) {
|
||||
var exists = false;
|
||||
var count = popularEmoji.length;
|
||||
var result = [];
|
||||
for (var i = 0; i < count; i++) {
|
||||
if (popularEmoji[i].code == code) {
|
||||
exists = true;
|
||||
popularEmoji[i].rate++;
|
||||
}
|
||||
result.push([popularEmoji[i].code, popularEmoji[i].rate]);
|
||||
}
|
||||
if (exists) {
|
||||
result.sort(function (a, b) {
|
||||
return b[1] - a[1];
|
||||
});
|
||||
} else {
|
||||
if (result.length > 41) {
|
||||
result = result.slice(0, 41);
|
||||
}
|
||||
result.push([code, 1]);
|
||||
}
|
||||
ConfigStorage.set({emojis_popular: result});
|
||||
});
|
||||
}
|
||||
|
||||
function indexEmojis () {
|
||||
if (index === false) {
|
||||
index = SearchIndexManager.createIndex();
|
||||
var shortcut;
|
||||
for (shortcut in shortcuts) {
|
||||
if (shortcuts.hasOwnProperty(shortcut)) {
|
||||
SearchIndexManager.indexObject(shortcuts[shortcut], shortcut, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function searchEmojis (q) {
|
||||
indexEmojis();
|
||||
var foundObject = SearchIndexManager.search(q, index);
|
||||
var foundCodes = [];
|
||||
var code;
|
||||
for (code in foundObject) {
|
||||
if (foundObject.hasOwnProperty(code)) {
|
||||
foundCodes.push(code);
|
||||
}
|
||||
}
|
||||
return foundCodes;
|
||||
}
|
||||
|
||||
global.EmojiHelper = {
|
||||
emojis: emojis,
|
||||
shortcuts: shortcuts,
|
||||
spritesheetPositions: spritesheetPositions,
|
||||
getPopularEmoji: getPopularEmoji,
|
||||
pushPopularEmoji: pushPopularEmoji,
|
||||
indexEmojis: indexEmojis,
|
||||
searchEmojis: searchEmojis
|
||||
};
|
||||
|
||||
})(window, Config.Emoji, Config.EmojiCategories, Config.EmojiCategorySpritesheetDimens);
|
||||
|
||||
|
||||
function EmojiTooltip (btnEl, options) {
|
||||
options = options || {};
|
||||
var self = this;
|
||||
|
||||
this.btnEl = $(btnEl);
|
||||
this.onEmojiSelected = options.onEmojiSelected;
|
||||
this.onStickerSelected = options.onStickerSelected;
|
||||
this.getStickers = options.getStickers;
|
||||
|
||||
$(this.btnEl).on('mouseenter mouseleave', function (e) {
|
||||
self.isOverBtn = e.type == 'mouseenter';
|
||||
self.createTooltip();
|
||||
|
||||
if (self.isOverBtn) {
|
||||
self.onMouseEnter(true);
|
||||
} else {
|
||||
self.onMouseLeave(true);
|
||||
}
|
||||
});
|
||||
$(this.btnEl).on('mousedown', function (e) {
|
||||
if (!self.shown) {
|
||||
clearTimeout(self.showTimeout);
|
||||
delete self.showTimeout;
|
||||
self.show();
|
||||
} else {
|
||||
clearTimeout(self.hideTimeout);
|
||||
delete self.hideTimeout;
|
||||
self.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
EmojiTooltip.prototype.onMouseEnter = function (triggerShow) {
|
||||
if (this.hideTimeout) {
|
||||
clearTimeout(this.hideTimeout);
|
||||
delete this.hideTimeout;
|
||||
}
|
||||
else if (triggerShow && !this.showTimeout) {
|
||||
this.showTimeout = setTimeout(this.show.bind(this), 500);
|
||||
}
|
||||
};
|
||||
|
||||
EmojiTooltip.prototype.onMouseLeave = function (triggerUnshow) {
|
||||
if (!this.hideTimeout) {
|
||||
var self = this;
|
||||
this.hideTimeout = setTimeout(function () {
|
||||
self.hide();
|
||||
}, 500);
|
||||
}
|
||||
else if (triggerUnshow && this.showTimeout) {
|
||||
clearTimeout(this.showTimeout);
|
||||
delete this.showTimeout;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
EmojiTooltip.prototype.createTooltip = function () {
|
||||
if (this.tooltipEl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
this.tooltipEl = $('<div class="composer_emoji_tooltip noselect"><div class="composer_emoji_tooltip_tabs"></div><div class="composer_emoji_tooltip_content_wrap nano mobile_scrollable_wrap"><div class="composer_emoji_tooltip_content nano-content clearfix"></div></div><div class="composer_emoji_tooltip_footer"><a class="composer_emoji_tooltip_settings"></a></div><div class="composer_emoji_tooltip_tail"><i class="icon icon-tooltip-tail"></i></div></div>').appendTo(document.body);
|
||||
|
||||
this.tabsEl = $('.composer_emoji_tooltip_tabs', this.tooltip);
|
||||
this.contentWrapEl = $('.composer_emoji_tooltip_content_wrap', this.tooltip);
|
||||
this.contentEl = $('.composer_emoji_tooltip_content', this.tooltip);
|
||||
this.footerEl = $('.composer_emoji_tooltip_footer', this.tooltip);
|
||||
this.settingsEl = $('.composer_emoji_tooltip_settings', this.tooltip);
|
||||
|
||||
angular.forEach(['recent', 'smile', 'flower', 'bell', 'car', 'grid', 'stickers'], function (tabName, tabIndex) {
|
||||
$('<a class="composer_emoji_tooltip_tab composer_emoji_tooltip_tab_' + tabName + '"></a>')
|
||||
.on('mousedown', function (e) {
|
||||
self.selectTab(tabIndex);
|
||||
return cancelEvent(e);
|
||||
})
|
||||
.on('mouseenter mouseleave', function (e) {
|
||||
clearTimeout(self.selectTabTimeout);
|
||||
if (e.type == 'mouseenter') {
|
||||
self.selectTabTimeout = setTimeout(function () {
|
||||
self.selectTab(tabIndex);
|
||||
}, 300);
|
||||
}
|
||||
})
|
||||
.appendTo(self.tabsEl);
|
||||
});
|
||||
|
||||
if (!Config.Mobile) {
|
||||
this.contentWrapEl.nanoScroller({preventPageScrolling: true, tabIndex: -1});
|
||||
}
|
||||
|
||||
this.contentEl.on('mousedown', function (e) {
|
||||
e = e.originalEvent || e;
|
||||
var target = $(e.target), code, sticker;
|
||||
if (target.hasClass('emoji') || target.hasClass('composer_sticker_image')) {
|
||||
target = $(target[0].parentNode);
|
||||
}
|
||||
if (code = target.attr('data-code')) {
|
||||
if (self.onEmojiSelected) {
|
||||
self.onEmojiSelected(code);
|
||||
}
|
||||
EmojiHelper.pushPopularEmoji(code);
|
||||
}
|
||||
if (sticker = target.attr('data-sticker')) {
|
||||
if (self.onStickerSelected) {
|
||||
self.onStickerSelected(sticker);
|
||||
}
|
||||
}
|
||||
return cancelEvent(e);
|
||||
});
|
||||
|
||||
this.tooltipEl.on('mouseenter mouseleave', function (e) {
|
||||
if (e.type == 'mouseenter') {
|
||||
self.onMouseEnter();
|
||||
} else {
|
||||
self.onMouseLeave();
|
||||
}
|
||||
});
|
||||
|
||||
this.selectTab(0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
EmojiTooltip.prototype.selectTab = function (tab) {
|
||||
if (this.tab === tab) {
|
||||
return false;
|
||||
}
|
||||
$('.active', this.tabsEl).removeClass('active');
|
||||
this.tab = tab;
|
||||
$(this.tabsEl[0].childNodes[tab]).addClass('active');
|
||||
|
||||
this.updateTabContents();
|
||||
};
|
||||
|
||||
EmojiTooltip.prototype.updateTabContents = function (tab) {
|
||||
var html = [];
|
||||
var self = this;
|
||||
var iconSize = Config.Mobile ? 26 : 20;
|
||||
|
||||
var renderContent = function () {
|
||||
self.contentEl.html(html.join(''));
|
||||
|
||||
if (!Config.Mobile) {
|
||||
setTimeout(function () {
|
||||
self.contentWrapEl.nanoScroller();
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.tab == 6) { // Stickers
|
||||
var renderStickers = function (stickers) {
|
||||
var sticker, i;
|
||||
var count = stickers.length;
|
||||
for (i = 0; i < count; i++) {
|
||||
sticker = stickers[i];
|
||||
html.push('<a class="composer_sticker_btn" data-sticker="' + sticker.id + '"><img class="composer_sticker_image" src="' + encodeEntities(sticker.src) + '" /></a>');
|
||||
}
|
||||
renderContent();
|
||||
};
|
||||
this.getStickers(renderStickers);
|
||||
}
|
||||
else if (this.tab > 0) {
|
||||
var categoryIndex = this.tab - 1;
|
||||
var emoticonCodes = Config.EmojiCategories[categoryIndex];
|
||||
var totalColumns = Config.EmojiCategorySpritesheetDimens[categoryIndex][1];
|
||||
var count = emoticonCodes.length;
|
||||
var emoticonCode, emoticonData, i, x, y;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
emoticonCode = emoticonCodes[i];
|
||||
emoticonData = Config.Emoji[emoticonCode];
|
||||
x = iconSize * (i % totalColumns);
|
||||
y = iconSize * Math.floor(i / totalColumns);
|
||||
html.push('<a class="composer_emoji_btn" title=":' + encodeEntities(emoticonData[1][0]) + ':" data-code="' + encodeEntities(emoticonCode) + '"><i class="emoji emoji-w' + iconSize + ' emoji-spritesheet-' + categoryIndex + '" style="background-position: -' + x + 'px -' + y + 'px;"></i></a>');
|
||||
}
|
||||
renderContent();
|
||||
}
|
||||
else {
|
||||
EmojiHelper.getPopularEmoji(function (popularEmoji) {
|
||||
var emoticonCode, emoticonData, spritesheet, pos, categoryIndex;
|
||||
var count = popularEmoji.length;
|
||||
var i, x, y;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
emoticonCode = popularEmoji[i].code;
|
||||
if (emoticonData = Config.Emoji[emoticonCode]) {
|
||||
spritesheet = EmojiHelper.spritesheetPositions[emoticonCode];
|
||||
categoryIndex = spritesheet[0];
|
||||
pos = spritesheet[1];
|
||||
x = iconSize * spritesheet[3];
|
||||
y = iconSize * spritesheet[2];
|
||||
html.push('<a class="composer_emoji_btn" title=":' + encodeEntities(emoticonData[1][0]) + ':" data-code="' + encodeEntities(emoticonCode) + '"><i class="emoji emoji-w' + iconSize + ' emoji-spritesheet-' + categoryIndex + '" style="background-position: -' + x + 'px -' + y + 'px;"></i></a>');
|
||||
}
|
||||
}
|
||||
renderContent();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
EmojiTooltip.prototype.updatePosition = function () {
|
||||
var offset = this.btnEl.offset();
|
||||
this.tooltipEl.css({top: offset.top, left: offset.left});
|
||||
};
|
||||
|
||||
EmojiTooltip.prototype.show = function () {
|
||||
this.updatePosition();
|
||||
this.tooltipEl.addClass('composer_emoji_tooltip_shown');
|
||||
this.btnEl.addClass('composer_emoji_insert_btn_on');
|
||||
delete this.showTimeout;
|
||||
this.shown = true;
|
||||
};
|
||||
|
||||
EmojiTooltip.prototype.hide = function () {
|
||||
this.tooltipEl.removeClass('composer_emoji_tooltip_shown');
|
||||
this.btnEl.removeClass('composer_emoji_insert_btn_on');
|
||||
delete this.hideTimeout;
|
||||
delete this.shown;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
function EmojiPanel (containerEl, options) {
|
||||
options = options || {};
|
||||
var self = this;
|
||||
|
||||
this.containerEl = $(containerEl);
|
||||
this.onEmojiSelected = options.onEmojiSelected;
|
||||
|
||||
this.containerEl.on('mousedown', function (e) {
|
||||
e = e.originalEvent || e;
|
||||
var target = $(e.target), code;
|
||||
if (target.hasClass('emoji')) {
|
||||
target = $(target[0].parentNode);
|
||||
}
|
||||
if (code = target.attr('data-code')) {
|
||||
if (self.onEmojiSelected) {
|
||||
self.onEmojiSelected(code);
|
||||
}
|
||||
EmojiHelper.pushPopularEmoji(code);
|
||||
}
|
||||
return cancelEvent(e);
|
||||
});
|
||||
|
||||
this.update();
|
||||
}
|
||||
|
||||
EmojiPanel.prototype.update = function () {
|
||||
var html = [];
|
||||
var self = this;
|
||||
var iconSize = Config.Mobile ? 26 : 20;
|
||||
|
||||
EmojiHelper.getPopularEmoji(function (popularEmoji) {
|
||||
var emoticonCode, emoticonData, spritesheet, pos, categoryIndex;
|
||||
var count = popularEmoji.length;
|
||||
var i, x, y;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
emoticonCode = popularEmoji[i].code;
|
||||
if (emoticonData = Config.Emoji[emoticonCode]) {
|
||||
spritesheet = EmojiHelper.spritesheetPositions[emoticonCode];
|
||||
categoryIndex = spritesheet[0];
|
||||
pos = spritesheet[1];
|
||||
x = iconSize * spritesheet[3];
|
||||
y = iconSize * spritesheet[2];
|
||||
html.push('<a class="composer_emoji_btn" title=":' + encodeEntities(emoticonData[1][0]) + ':" data-code="' + encodeEntities(emoticonCode) + '"><i class="emoji emoji-w20 emoji-spritesheet-' + categoryIndex + '" style="background-position: -' + x + 'px -' + y + 'px;"></i></a>');
|
||||
}
|
||||
}
|
||||
self.containerEl.html(html.join(''));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function MessageComposer (textarea, options) {
|
||||
this.textareaEl = $(textarea);
|
||||
|
||||
this.setUpInput();
|
||||
|
||||
this.autoCompleteEl = $('<ul class="composer_dropdown dropdown-menu"></ul>').appendTo(document.body);
|
||||
|
||||
var self = this;
|
||||
this.autoCompleteEl.on('mousedown', function (e) {
|
||||
e = e.originalEvent || e;
|
||||
var target = $(e.target), code;
|
||||
if (target.hasClass('emoji') || target.hasClass('composer_emoji_shortcut')) {
|
||||
target = $(target[0].parentNode);
|
||||
}
|
||||
if (code = target.attr('data-code')) {
|
||||
if (self.onEmojiSelected) {
|
||||
self.onEmojiSelected(code, true);
|
||||
}
|
||||
EmojiHelper.pushPopularEmoji(code);
|
||||
}
|
||||
return cancelEvent(e);
|
||||
});
|
||||
|
||||
this.isActive = false;
|
||||
|
||||
this.onTyping = options.onTyping;
|
||||
this.onMessageSubmit = options.onMessageSubmit;
|
||||
this.getSendOnEnter = options.getSendOnEnter;
|
||||
}
|
||||
|
||||
MessageComposer.prototype.setUpInput = function () {
|
||||
if ('contentEditable' in document.body) {
|
||||
this.setUpRich();
|
||||
} else {
|
||||
this.setUpPlaintext();
|
||||
}
|
||||
}
|
||||
|
||||
MessageComposer.prototype.setUpRich = function () {
|
||||
this.textareaEl.hide();
|
||||
this.richTextareaEl = $('<div class="composer_rich_textarea" contenteditable="true"></div>');
|
||||
|
||||
this.textareaEl[0].parentNode.insertBefore(this.richTextareaEl[0], this.textareaEl[0]);
|
||||
|
||||
this.richTextareaEl.on('keyup keydown', this.onKeyEvent.bind(this));
|
||||
this.richTextareaEl.on('focus blur', this.onFocusBlur.bind(this));
|
||||
this.richTextareaEl.on('paste', this.onRichPaste.bind(this));
|
||||
this.richTextareaEl.on('DOMNodeInserted', this.onRichPasteNode.bind(this));
|
||||
|
||||
$(document.body).on('keydown', this.backupSelection.bind(this));
|
||||
}
|
||||
|
||||
MessageComposer.prototype.setUpPlaintext = function () {
|
||||
this.textareaEl.on('keyup keydown', this.onKeyEvent.bind(this));
|
||||
this.textareaEl.on('focus blur', this.onFocusBlur.bind(this));
|
||||
}
|
||||
|
||||
MessageComposer.prototype.onKeyEvent = function (e) {
|
||||
var self = this;
|
||||
if (e.type == 'keyup') {
|
||||
this.checkAutocomplete();
|
||||
|
||||
if (this.onTyping) {
|
||||
var now = tsNow();
|
||||
if (now - this.lastTyping > 5000) {
|
||||
var length = (this.richTextareaEl ? this.richTextareaEl[0].textContent : this.textareaEl[0].value).length;
|
||||
|
||||
if (length != this.lastLength) {
|
||||
this.lastTyping = now;
|
||||
this.lastLength = length;
|
||||
this.onTyping();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.richTextareaEl) {
|
||||
clearTimeout(this.updateValueTO);
|
||||
var now = tsNow();
|
||||
if (this.keyupStarted === undefined) {
|
||||
this.keyupStarted = now;
|
||||
}
|
||||
if (now - this.keyupStarted > 10000) {
|
||||
this.onChange();
|
||||
}
|
||||
else {
|
||||
this.updateValueTO = setTimeout(this.onChange.bind(this), 1000);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (e.type == 'keydown') {
|
||||
if (this.autocompleteShown) {
|
||||
if (e.keyCode == 38 || e.keyCode == 40) { // UP / DOWN
|
||||
var next = e.keyCode == 40;
|
||||
var currentSelected = $(this.autoCompleteEl).find('.composer_emoji_option_active');
|
||||
|
||||
if (currentSelected.length) {
|
||||
var currentSelectedWrap = currentSelected[0].parentNode;
|
||||
var nextWrap = currentSelectedWrap[next ? 'nextSibling' : 'previousSibling'];
|
||||
currentSelected.removeClass('composer_emoji_option_active');
|
||||
if (nextWrap) {
|
||||
$(nextWrap).find('a').addClass('composer_emoji_option_active');
|
||||
return cancelEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
var childNodes = this.autoCompleteEl[0].childNodes;
|
||||
var nextWrap = childNodes[next ? 0 : childNodes.length - 1];
|
||||
$(nextWrap).find('a').addClass('composer_emoji_option_active');
|
||||
|
||||
return cancelEvent(e);
|
||||
}
|
||||
|
||||
if (e.keyCode == 13) { // ENTER
|
||||
var currentSelected = $(this.autoCompleteEl).find('.composer_emoji_option_active') ||
|
||||
$(this.autoCompleteEl).childNodes[0].find('a');
|
||||
var code = currentSelected.attr('data-code');
|
||||
if (code) {
|
||||
this.onEmojiSelected(code, true);
|
||||
EmojiHelper.pushPopularEmoji(code);
|
||||
}
|
||||
return cancelEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
else if (e.keyCode == 13) {
|
||||
var submit = false;
|
||||
var sendOnEnter = true;
|
||||
if (this.getSendOnEnter && !this.getSendOnEnter()) {
|
||||
sendOnEnter = false;
|
||||
}
|
||||
if (sendOnEnter && !e.shiftKey) {
|
||||
submit = true;
|
||||
} else if (!sendOnEnter && (e.ctrlKey || e.metaKey)) {
|
||||
submit = true;
|
||||
}
|
||||
|
||||
if (submit) {
|
||||
this.onMessageSubmit(e);
|
||||
return cancelEvent(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MessageComposer.prototype.backupSelection = function () {
|
||||
delete this.selection;
|
||||
|
||||
if (!this.isActive) {
|
||||
return;
|
||||
}
|
||||
if (window.getSelection) {
|
||||
var sel = window.getSelection();
|
||||
if (sel.getRangeAt && sel.rangeCount) {
|
||||
this.selection = sel.getRangeAt(0);
|
||||
}
|
||||
} else if (document.selection && document.selection.createRange) {
|
||||
this.selection = document.selection.createRange();
|
||||
}
|
||||
}
|
||||
|
||||
MessageComposer.prototype.restoreSelection = function () {
|
||||
if (!this.selection) {
|
||||
return false;
|
||||
}
|
||||
var result = false;
|
||||
if (window.getSelection) {
|
||||
var sel = window.getSelection();
|
||||
sel.removeAllRanges();
|
||||
sel.addRange(this.selection);
|
||||
result = true;
|
||||
}
|
||||
else if (document.selection && this.selection.select) {
|
||||
this.selection.select();
|
||||
result = true;
|
||||
}
|
||||
delete this.selection;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
MessageComposer.prototype.checkAutocomplete = function () {
|
||||
var pos, value;
|
||||
if (this.richTextareaEl) {
|
||||
var textarea = this.richTextareaEl[0];
|
||||
var valueCaret = getRichValueWithCaret(textarea);
|
||||
var value = valueCaret[0];
|
||||
var pos = valueCaret[1] >= 0 ? valueCaret[1] : value.length;
|
||||
} else {
|
||||
var textarea = this.textareaEl[0];
|
||||
var pos = getFieldSelection(textarea);
|
||||
var value = textarea.value;
|
||||
}
|
||||
|
||||
value = value.substr(0, pos);
|
||||
|
||||
var matches = value.match(/(?:\s|^):([A-Za-z0-9\-\+\*_]*)$/);
|
||||
if (matches) {
|
||||
if (this.previousQuery == matches[0]) {
|
||||
return;
|
||||
}
|
||||
this.previousQuery = matches[0];
|
||||
var query = SearchIndexManager.cleanSearchText(matches[1]);
|
||||
EmojiHelper.getPopularEmoji((function (popular) {
|
||||
if (query.length) {
|
||||
var found = EmojiHelper.searchEmojis(query);
|
||||
if (found.length) {
|
||||
var popularFound = [],
|
||||
code, pos;
|
||||
for (var i = 0, len = popular.length; i < len; i++) {
|
||||
code = popular[i].code;
|
||||
pos = found.indexOf(code);
|
||||
if (pos >= 0) {
|
||||
popularFound.push(code);
|
||||
found.splice(pos, 1);
|
||||
if (!found.length) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.showEmojiSuggestions(popularFound.concat(found));
|
||||
} else {
|
||||
this.hideSuggestions();
|
||||
}
|
||||
} else {
|
||||
this.showEmojiSuggestions(popular);
|
||||
}
|
||||
}).bind(this));
|
||||
}
|
||||
else {
|
||||
delete this.previousQuery;
|
||||
this.hideSuggestions();
|
||||
}
|
||||
}
|
||||
|
||||
MessageComposer.prototype.onFocusBlur = function (e) {
|
||||
this.isActive = e.type == 'focus';
|
||||
|
||||
if (!this.isActive) {
|
||||
this.hideSuggestions();
|
||||
} else {
|
||||
setTimeout(this.checkAutocomplete.bind(this), 100);
|
||||
}
|
||||
if (this.richTextareaEl) {
|
||||
document.execCommand('enableObjectResizing', !this.isActive, !this.isActive);
|
||||
}
|
||||
}
|
||||
|
||||
MessageComposer.prototype.onRichPaste = function (e) {
|
||||
var cData = (e.originalEvent || e).clipboardData,
|
||||
items = cData && cData.items || [],
|
||||
i;
|
||||
for (i = 0; i < items.length; i++) {
|
||||
if (items[i].kind == 'file') {
|
||||
e.preventDefault();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
var text = (e.originalEvent || e).clipboardData.getData('text/plain');
|
||||
setZeroTimeout(this.onChange.bind(this), 0);
|
||||
if (text.length) {
|
||||
document.execCommand('insertText', false, text);
|
||||
return cancelEvent(e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
MessageComposer.prototype.onRichPasteNode = function (e) {
|
||||
var element = (e.originalEvent || e).target,
|
||||
src = (element || {}).src || '',
|
||||
remove = false;
|
||||
|
||||
if (src.substr(0, 5) == 'data:') {
|
||||
remove = true;
|
||||
var blob = dataUrlToBlob(src);
|
||||
this.onFilePaste(blob);
|
||||
setZeroTimeout(function () {
|
||||
element.parentNode.removeChild(element);
|
||||
})
|
||||
}
|
||||
else if (src && !src.match(/img\/blank\.gif/)) {
|
||||
var replacementNode = document.createTextNode(' ' + src + ' ');
|
||||
setTimeout(function () {
|
||||
element.parentNode.replaceChild(replacementNode, element);
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
MessageComposer.prototype.onEmojiSelected = function (code, autocomplete) {
|
||||
if (this.richTextareaEl) {
|
||||
var textarea = this.richTextareaEl[0];
|
||||
if (!this.isActive) {
|
||||
if (!this.restoreSelection()) {
|
||||
setRichFocus(textarea);
|
||||
}
|
||||
}
|
||||
if (autocomplete) {
|
||||
var valueCaret = getRichValueWithCaret(textarea);
|
||||
var fullValue = valueCaret[0];
|
||||
var pos = valueCaret[1] >= 0 ? valueCaret[1] : fullValue.length;
|
||||
var suffix = fullValue.substr(pos);
|
||||
var prefix = fullValue.substr(0, pos);
|
||||
var matches = prefix.match(/:([A-Za-z0-9\-\+\*_]*)$/);
|
||||
var emoji = EmojiHelper.emojis[code];
|
||||
|
||||
var newValuePrefix;
|
||||
if (matches && matches[0]) {
|
||||
newValuePrefix = prefix.substr(0, matches.index) + ':' + emoji[1] + ':';
|
||||
} else {
|
||||
newValuePrefix = prefix + ':' + emoji[1] + ':';
|
||||
}
|
||||
textarea.value = newValue;
|
||||
|
||||
this.selId = (this.selId || 0) + 1;
|
||||
var html = this.getRichHtml(newValuePrefix) + ' <span id="composer_sel' + this.selId + '"></span>' + this.getRichHtml(suffix);
|
||||
|
||||
this.richTextareaEl.html(html);
|
||||
setRichFocus(textarea, $('#composer_sel' + this.selId)[0]);
|
||||
} else {
|
||||
document.execCommand('insertHTML', false, this.getEmojiHtml(code));
|
||||
}
|
||||
}
|
||||
else {
|
||||
var textarea = this.textareaEl[0];
|
||||
var fullValue = textarea.value;
|
||||
var pos = this.isActive ? getFieldSelection(textarea) : fullValue.length;
|
||||
var suffix = fullValue.substr(pos);
|
||||
var prefix = fullValue.substr(0, pos);
|
||||
var matches = autocomplete && prefix.match(/:([A-Za-z0-9\-\+\*_]*)$/);
|
||||
var emoji = EmojiHelper.emojis[code];
|
||||
|
||||
if (matches && matches[0]) {
|
||||
var newValue = prefix.substr(0, matches.index) + ':' + emoji[1] + ': ' + suffix;
|
||||
var newPos = matches.index + emoji[1].length + 3;
|
||||
} else {
|
||||
var newValue = prefix + ':' + emoji[1] + ': ' + suffix;
|
||||
var newPos = prefix.length + emoji[1].length + 3;
|
||||
}
|
||||
textarea.value = newValue;
|
||||
setFieldSelection(textarea, newPos);
|
||||
}
|
||||
|
||||
this.hideSuggestions();
|
||||
this.onChange();
|
||||
}
|
||||
|
||||
MessageComposer.prototype.onChange = function (e) {
|
||||
if (this.richTextareaEl) {
|
||||
delete this.keyupStarted;
|
||||
this.textareaEl.val(getRichValue(this.richTextareaEl[0])).trigger('change');
|
||||
}
|
||||
}
|
||||
|
||||
MessageComposer.prototype.getEmojiHtml = function (code, emoji) {
|
||||
emoji = emoji || EmojiHelper.emojis[code];
|
||||
var iconSize = 20;
|
||||
var spritesheet = EmojiHelper.spritesheetPositions[code];
|
||||
var categoryIndex = spritesheet[0];
|
||||
var pos = spritesheet[1];
|
||||
var x = iconSize * spritesheet[3];
|
||||
var y = iconSize * spritesheet[2];
|
||||
|
||||
return '<img src="img/blank.gif" alt=":' + encodeEntities(emoji[1]) + ':" data-code="' + encodeEntities(code) + '" class="emoji emoji-w20 emoji-spritesheet-' + categoryIndex + '" style="background-position: -' + x + 'px -' + y + 'px;" onresizestart="return false" />';
|
||||
}
|
||||
|
||||
MessageComposer.prototype.setValue = function (text) {
|
||||
if (this.richTextareaEl) {
|
||||
this.richTextareaEl.html(this.getRichHtml(text));
|
||||
this.lastLength = text.length;
|
||||
} else {
|
||||
this.textareaEl.val(text);
|
||||
}
|
||||
}
|
||||
|
||||
MessageComposer.prototype.getRichHtml = function (text) {
|
||||
return $('<div>').text(text).html().replace(/:([A-Za-z0-9\-\+\*_]+?):/gi, (function (all, shortcut) {
|
||||
var code = EmojiHelper.shortcuts[shortcut];
|
||||
if (code !== undefined) {
|
||||
return this.getEmojiHtml(code);
|
||||
}
|
||||
return all;
|
||||
}).bind(this));
|
||||
}
|
||||
|
||||
|
||||
MessageComposer.prototype.focus = function () {
|
||||
if (this.richTextareaEl) {
|
||||
setZeroTimeout((function () {
|
||||
setRichFocus(this.richTextareaEl[0]);
|
||||
}).bind(this));
|
||||
} else {
|
||||
setFieldSelection(this.textareaEl[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MessageComposer.prototype.showEmojiSuggestions = function (codes) {
|
||||
var html = [];
|
||||
var iconSize = Config.Mobile ? 26 : 20;
|
||||
|
||||
var emoticonCode, emoticonData, spritesheet, pos, categoryIndex;
|
||||
var count = Math.min(5, codes.length);
|
||||
var i, x, y;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
emoticonCode = codes[i];
|
||||
if (emoticonCode.code) {
|
||||
emoticonCode = emoticonCode.code;
|
||||
}
|
||||
if (emoticonData = Config.Emoji[emoticonCode]) {
|
||||
spritesheet = EmojiHelper.spritesheetPositions[emoticonCode];
|
||||
categoryIndex = spritesheet[0];
|
||||
pos = spritesheet[1];
|
||||
x = iconSize * spritesheet[3];
|
||||
y = iconSize * spritesheet[2];
|
||||
html.push('<li><a class="composer_emoji_option" data-code="' + encodeEntities(emoticonCode) + '"><i class="emoji emoji-w20 emoji-spritesheet-' + categoryIndex + '" style="background-position: -' + x + 'px -' + y + 'px;"></i><span class="composer_emoji_shortcut">:' + encodeEntities(emoticonData[1][0]) + ':</span></a></li>');
|
||||
}
|
||||
}
|
||||
|
||||
this.autoCompleteEl.html(html.join(''));
|
||||
this.autoCompleteEl.show();
|
||||
this.updatePosition();
|
||||
this.autocompleteShown = true;
|
||||
}
|
||||
|
||||
MessageComposer.prototype.updatePosition = function () {
|
||||
var offset = (this.richTextareaEl || this.textareaEl).offset();
|
||||
var height = this.autoCompleteEl.outerHeight();
|
||||
this.autoCompleteEl.css({top: offset.top - height, left: offset.left});
|
||||
}
|
||||
|
||||
MessageComposer.prototype.hideSuggestions = function () {
|
||||
this.autoCompleteEl.hide();
|
||||
delete this.autocompleteShown;
|
||||
}
|
||||
|
||||
MessageComposer.prototype.resetTyping = function () {
|
||||
this.lastTyping = 0;
|
||||
this.lastLength = 0;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
|
||||
.service('AppUsersManager', function ($rootScope, $modal, $modalStack, $filter, $q, qSync, MtpApiFileManager, MtpApiManager, RichTextProcessor, SearchIndexManager, ErrorService, Storage, _) {
|
||||
.service('AppUsersManager', function ($rootScope, $modal, $modalStack, $filter, $q, qSync, MtpApiFileManager, MtpApiManager, RichTextProcessor, ErrorService, Storage, _) {
|
||||
var users = {},
|
||||
usernames = {},
|
||||
cachedPhotoLocations = {},
|
||||
@ -507,8 +507,9 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
|
||||
})
|
||||
|
||||
.service('AppChatsManager', function ($rootScope, $modal, _, MtpApiFileManager, MtpApiManager, AppUsersManager, RichTextProcessor, SearchIndexManager) {
|
||||
.service('AppChatsManager', function ($rootScope, $modal, _, MtpApiFileManager, MtpApiManager, AppUsersManager, RichTextProcessor) {
|
||||
var chats = {},
|
||||
chatsFull = {},
|
||||
cachedPhotoLocations = {};
|
||||
|
||||
function saveApiChats (apiChats) {
|
||||
@ -687,7 +688,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
}
|
||||
})
|
||||
|
||||
.service('AppMessagesManager', function ($q, $rootScope, $location, $filter, ApiUpdatesManager, AppUsersManager, AppChatsManager, AppPeersManager, AppPhotosManager, AppVideoManager, AppDocsManager, AppAudioManager, MtpApiManager, MtpApiFileManager, RichTextProcessor, NotificationsManager, SearchIndexManager, PeersSelectService, Storage, FileManager, TelegramMeWebService, StatusManager, _) {
|
||||
.service('AppMessagesManager', function ($q, $rootScope, $location, $filter, ApiUpdatesManager, AppUsersManager, AppChatsManager, AppPeersManager, AppPhotosManager, AppVideoManager, AppDocsManager, AppAudioManager, MtpApiManager, MtpApiFileManager, RichTextProcessor, NotificationsManager, PeersSelectService, Storage, FileManager, TelegramMeWebService, StatusManager, _) {
|
||||
|
||||
var messagesStorage = {};
|
||||
var messagesForHistory = {};
|
||||
@ -1548,7 +1549,17 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
break;
|
||||
|
||||
case 'inputMediaPhoto':
|
||||
media = {photo: AppPhotosManager.getPhoto(inputMedia.id.id)};
|
||||
media = {
|
||||
_: 'messageMediaPhoto',
|
||||
photo: AppPhotosManager.getPhoto(inputMedia.id.id)
|
||||
};
|
||||
break;
|
||||
|
||||
case 'inputMediaDocument':
|
||||
media = {
|
||||
_: 'messageMediaDocument',
|
||||
'document': AppDocsManager.getDoc(inputMedia.id.id)
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2752,6 +2763,10 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
});
|
||||
};
|
||||
|
||||
function getDoc (docID) {
|
||||
return docs[docID] || {_: 'documentEmpty'};
|
||||
}
|
||||
|
||||
function wrapForHistory (docID) {
|
||||
if (docsForHistory[docID] !== undefined) {
|
||||
return docsForHistory[docID];
|
||||
@ -2911,6 +2926,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
|
||||
return {
|
||||
saveDoc: saveDoc,
|
||||
getDoc: getDoc,
|
||||
wrapForHistory: wrapForHistory,
|
||||
updateDocDownloaded: updateDocDownloaded,
|
||||
downloadDoc: downloadDoc,
|
||||
@ -3024,6 +3040,111 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
}
|
||||
})
|
||||
|
||||
.service('AppStickersManager', function ($q, FileManager, MtpApiManager, MtpApiFileManager, AppDocsManager, Storage) {
|
||||
|
||||
var stickersToEmoji = {};
|
||||
var currentStickers = [];
|
||||
var applied = false;
|
||||
var started = false;
|
||||
|
||||
return {
|
||||
start: start,
|
||||
getStickerEmoji: getStickerEmoji,
|
||||
getStickers: getStickers,
|
||||
getStickersImages: getStickersImages
|
||||
};
|
||||
|
||||
function start () {
|
||||
if (!started) {
|
||||
started = true;
|
||||
setTimeout(getStickers, 1000);
|
||||
setInterval(preloadStickers, 900000);
|
||||
}
|
||||
}
|
||||
|
||||
function preloadStickers() {
|
||||
getStickers().then(getStickersImages);
|
||||
}
|
||||
|
||||
function getStickerEmoji(docID) {
|
||||
return stickersToEmoji[docID] || false;
|
||||
}
|
||||
|
||||
function processRawStickers(stickers) {
|
||||
if (applied !== stickers.hash) {
|
||||
applied = stickers.hash;
|
||||
var i, j, len1, len2;
|
||||
|
||||
len1 = stickers.documents.length;
|
||||
for (i = 0; i < len1; i++) {
|
||||
AppDocsManager.saveDoc(stickers.documents[i]);
|
||||
}
|
||||
|
||||
var pack, emoticon, docID;
|
||||
var doneDocIDs = {};
|
||||
stickersToEmoji = {};
|
||||
currentStickers = [];
|
||||
len1 = stickers.packs.length;
|
||||
for (i = 0; i < len1; i++) {
|
||||
pack = stickers.packs[i];
|
||||
emoticon = pack.emoticon;
|
||||
len2 = pack.documents.length;
|
||||
for (j = 0; j < len2; j++) {
|
||||
docID = pack.documents[j];
|
||||
if (stickersToEmoji[docID] === undefined) {
|
||||
stickersToEmoji[docID] = emoticon;
|
||||
}
|
||||
if (doneDocIDs[docID] === undefined) {
|
||||
doneDocIDs[docID] = true;
|
||||
currentStickers.push(docID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return currentStickers;
|
||||
}
|
||||
|
||||
function getStickers () {
|
||||
return Storage.get('all_stickers').then(function (stickers) {
|
||||
var layer = Config.Schema.API.layer;
|
||||
if (stickers.layer != layer) {
|
||||
stickers = false;
|
||||
}
|
||||
if (stickers && stickers.date > tsNow(true)) {
|
||||
return processRawStickers(stickers);
|
||||
}
|
||||
return MtpApiManager.invokeApi('messages.getAllStickers', {
|
||||
hash: stickers && stickers.hash || ''
|
||||
}).then(function (newStickers) {
|
||||
if (newStickers._ == 'messages.allStickersNotModified') {
|
||||
newStickers = stickers;
|
||||
}
|
||||
newStickers.date = tsNow(true) + 3600;
|
||||
newStickers.layer = layer;
|
||||
delete newStickers._;
|
||||
Storage.set({all_stickers: newStickers});
|
||||
|
||||
return processRawStickers(newStickers);
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
function getStickersImages () {
|
||||
var promises = [];
|
||||
angular.forEach(currentStickers, function (docID) {
|
||||
var doc = AppDocsManager.getDoc(docID);
|
||||
var promise = MtpApiFileManager.downloadSmallFile(doc.thumb.location).then(function (blob) {
|
||||
return {
|
||||
id: docID,
|
||||
src: FileManager.getUrl(blob, 'image/webp')
|
||||
};
|
||||
});
|
||||
promises.push(promise);
|
||||
});
|
||||
return $q.all(promises);
|
||||
}
|
||||
})
|
||||
|
||||
.service('ApiUpdatesManager', function ($rootScope, MtpNetworkerFactory, AppUsersManager, AppChatsManager, AppPeersManager, MtpApiManager) {
|
||||
|
||||
var isSynchronizing = true,
|
||||
|
26
app/partials/desktop/emoji_btn_tooltip.html
Normal file
@ -0,0 +1,26 @@
|
||||
<div class="composer_emoji_btn_wrap">
|
||||
|
||||
<div class="composer_emoji_tooltip_wrap">
|
||||
<div class="composer_emoji_tooltip">
|
||||
|
||||
<div class="composer_emoji_tooltip_tabs">
|
||||
<a ng-repeat="tab in ::tabs" href="" class="composer_emoji_tooltip_tab" ng-class="['composer_emoji_tooltip_tab_' + tab, curTab == tab ? 'active' : '']" ng-click="tabSelect(tab)"></a>
|
||||
</div>
|
||||
|
||||
<div class="composer_emoji_content" ng-switch="curTab == 'stickers'">
|
||||
<div ng-switch-when="true" class="composer_emoji_content_emoticons">
|
||||
<a class="composer_emoticon_option" href="" ng-repeat="emoji in emojis" ng-click="emojiSelect(emoji)"></a>
|
||||
</div>
|
||||
<div ng-switch-default class="composer_emoji_content_stickers">
|
||||
<a class="composer_sticker_option" href="" ng-repeat="sticker in stickers" ng-click="stickerSelect(sticker)"></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a class="composer_emoji_btn">
|
||||
<i class="icon icon-emoji"></i>
|
||||
</a>
|
||||
|
||||
</div>
|
@ -168,9 +168,8 @@
|
||||
<form my-send-form draft-message="draftMessage" class="im_send_form" ng-class="{im_send_form_empty: !draftMessage.text.length}">
|
||||
|
||||
<div class="im_send_field_wrap">
|
||||
<div class="im_emoji_btn pull-right" title="{{'im_emoji_btn_title' | i18n}}">
|
||||
<i class="icon icon-emoji"></i>
|
||||
</div>
|
||||
<a class="composer_emoji_insert_btn"><i class="icon icon-emoji"></i></a>
|
||||
|
||||
<div class="im_send_dropbox_wrap" my-i18n="im_photos_drop_text"></div>
|
||||
<textarea ng-model="draftMessage.text" placeholder="{{'im_message_field_placeholder' | i18n}}" class="form-control im_message_field no_outline"></textarea>
|
||||
</div>
|
||||
@ -188,7 +187,7 @@
|
||||
<i class="icon icon-camera"></i>
|
||||
</div>
|
||||
|
||||
<div class="im_emoji_quick_select_area"></div>
|
||||
<div class="composer_emoji_panel"></div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
|
@ -133,9 +133,7 @@
|
||||
<i class="icon icon-paperclip"></i>
|
||||
</div>
|
||||
|
||||
<div class="im_emoji_btn pull-right" title="{{'im_emoji_btn_title' | i18n}}">
|
||||
<i class="icon icon-emoji"></i>
|
||||
</div>
|
||||
<a class="composer_emoji_insert_btn pull-right"><i class="icon icon-emoji"></i></a>
|
||||
|
||||
<button type="submit" class="btn btn-success im_submit"></button>
|
||||
</form>
|
||||
|
@ -1,6 +1,6 @@
|
||||
CACHE MANIFEST
|
||||
|
||||
# 55
|
||||
# 59
|
||||
|
||||
NETWORK:
|
||||
*
|
||||
|