diff --git a/app/js/controllers.js b/app/js/controllers.js
index 9912e915..da11e08c 100644
--- a/app/js/controllers.js
+++ b/app/js/controllers.js
@@ -995,6 +995,8 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.selectedFlush = selectedFlush;
$scope.botStart = botStart;
+ $scope.replyKeyboardToggle = replyKeyboardToggle;
+
$scope.toggleEdit = toggleEdit;
$scope.toggleMedia = toggleMedia;
$scope.returnToRecent = returnToRecent;
@@ -1393,7 +1395,17 @@ angular.module('myApp.controllers', ['myApp.i18n'])
}
console.log('update reply markup', peerID, replyKeyboard);
$scope.historyState.replyKeyboard = replyKeyboard;
- $scope.$broadcast('ui_panel_update');
+ $scope.$broadcast('ui_keyboard_update');
+ }
+
+ function replyKeyboardToggle () {
+ var replyKeyboard = $scope.historyState.replyKeyboard;
+ if (!replyKeyboard) {
+ return;
+ }
+ replyKeyboard.pFlags.hidden = !replyKeyboard.pFlags.hidden;
+ console.log('toggle reply markup', peerID, replyKeyboard);
+ $scope.$broadcast('ui_keyboard_update');
}
function botStart () {
@@ -1859,7 +1871,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.$on('user_update', angular.noop);
})
- .controller('AppImSendController', function ($scope, $timeout, MtpApiManager, Storage, AppProfileManager, AppChatsManager, AppUsersManager, AppPeersManager, AppDocsManager, AppMessagesManager, MtpApiFileManager) {
+ .controller('AppImSendController', function ($scope, $timeout, MtpApiManager, Storage, AppProfileManager, AppChatsManager, AppUsersManager, AppPeersManager, AppDocsManager, AppMessagesManager, MtpApiFileManager, RichTextProcessor) {
$scope.$watch('curDialog.peer', resetDraft);
$scope.$on('user_update', angular.noop);
@@ -1876,6 +1888,8 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.$watch('draftMessage.sticker', onStickerSelected);
$scope.$watch('draftMessage.command', onCommandSelected);
+ $scope.enterSlash = enterSlash;
+
function sendMessage (e) {
$scope.$broadcast('ui_message_before_send');
@@ -1974,7 +1988,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
commandsList.push({
botID: peerBot.id,
value: value,
- description: description
+ rDescription: RichTextProcessor.wrapRichText(description, {noLinks: true, noLineBreaks: true})
});
SearchIndexManager.indexObject(value, botSearchText + ' ' + command + ' ' + description, commandsIndex);
})
@@ -2017,6 +2031,12 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.$broadcast('ui_peer_reply');
}
+ function enterSlash (event) {
+ $scope.draftMessage.text = '/';
+ $scope.$broadcast('ui_peer_draft');
+ return cancelEvent(event);
+ }
+
function onMessageChange(newVal) {
// console.log('ctrl text changed', newVal);
// console.trace('ctrl text changed', newVal);
diff --git a/app/js/directives.js b/app/js/directives.js
index afb793c9..4cd92a48 100755
--- a/app/js/directives.js
+++ b/app/js/directives.js
@@ -414,9 +414,26 @@ angular.module('myApp.directives', ['myApp.filters'])
};
function link ($scope, element, attrs) {
+ var scrollable = $('.reply_markup', element);
+ var scroller = new Scroller(scrollable, {
+ classPrefix: 'reply_markup',
+ maxHeight: 170
+ });
$scope.buttonSend = function (button) {
$scope.$emit('reply_button_press', button);
}
+
+ $scope.$on('ui_keyboard_update', function () {
+ onContentLoaded(function () {
+ scroller.updateHeight();
+ scroller.scrollTo(0);
+ $scope.$emit('ui_panel_update');
+ })
+ });
+ onContentLoaded(function () {
+ scroller.updateHeight();
+ $scope.$emit('ui_panel_update');
+ });
}
})
@@ -1474,6 +1491,9 @@ angular.module('myApp.directives', ['myApp.filters'])
if (!Config.Navigator.touch) {
composer.focus();
}
+ onContentLoaded(function () {
+ composer.checkAutocomplete(true);
+ });
if (emojiTooltip) {
emojiTooltip.hide();
}
diff --git a/app/js/message_composer.js b/app/js/message_composer.js
index c2155e7c..ecbd5e43 100644
--- a/app/js/message_composer.js
+++ b/app/js/message_composer.js
@@ -196,21 +196,6 @@ EmojiTooltip.prototype.onMouseLeave = function (triggerUnshow) {
}
};
-EmojiTooltip.prototype.getScrollWidth = function() {
- var outer = $('
').css({
- position: 'absolute',
- width: 100,
- height: 100,
- overflow: 'scroll',
- top: -9999
- }).appendTo($(document.body));
-
- var scrollbarWidth = outer[0].offsetWidth - outer[0].clientWidth;
- outer.remove();
-
- return scrollbarWidth;
-};
-
EmojiTooltip.prototype.createTooltip = function () {
@@ -219,20 +204,12 @@ EmojiTooltip.prototype.createTooltip = function () {
}
var self = this;
- this.tooltipEl = $('
').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);
-
- var scrollWidth = this.getScrollWidth();
- if (scrollWidth > 0) {
- this.tooltipEl.css({
- width: parseInt(this.tooltipEl.css('width')) + scrollWidth
- });
- }
+ this.tooltipEl = $('
').appendTo(document.body);
+
+ this.tabsEl = $('.composer_emoji_tooltip_tabs', this.tooltipEl);
+ this.contentEl = $('.composer_emoji_tooltip_content', this.tooltipEl);
+ this.footerEl = $('.composer_emoji_tooltip_footer', this.tooltipEl);
+ this.settingsEl = $('.composer_emoji_tooltip_settings', this.tooltipEl);
angular.forEach(['recent', 'smile', 'flower', 'bell', 'car', 'grid', 'stickers'], function (tabName, tabIndex) {
var tab = $('
')
@@ -254,9 +231,7 @@ EmojiTooltip.prototype.createTooltip = function () {
}
});
- if (!Config.Mobile) {
- this.contentWrapEl.nanoScroller({preventPageScrolling: true, tabIndex: -1});
- }
+ this.scroller = new Scroller(this.contentEl, {classPrefix: 'composer_emoji_tooltip'});
this.contentEl.on('mousedown', function (e) {
e = e.originalEvent || e;
@@ -323,13 +298,7 @@ EmojiTooltip.prototype.updateTabContents = function () {
var renderContent = function () {
self.contentEl.html(html.join(''));
-
- if (!Config.Mobile) {
- self.contentWrapEl.nanoScroller({scroll: 'top'});
- setTimeout(function () {
- self.contentWrapEl.nanoScroller();
- }, 100);
- }
+ self.scroller.reinit();
}
if (this.tab == 6) { // Stickers
@@ -488,12 +457,9 @@ function MessageComposer (textarea, options) {
this.setUpInput();
this.autoCompleteWrapEl = $('
').appendTo(document.body);
- this.autoCompleteScrollerEl = $('
').appendTo(this.autoCompleteWrapEl);
- this.autoCompleteEl = $('').appendTo(this.autoCompleteScrollerEl);
+ this.autoCompleteEl = $('').appendTo(this.autoCompleteWrapEl);
- if (!Config.Mobile) {
- this.autoCompleteScrollerEl.nanoScroller({preventPageScrolling: true, tabIndex: -1});
- }
+ this.scroller = new Scroller(this.autoCompleteEl, {maxHeight: 180});
var self = this;
this.autoCompleteEl.on('mousedown', function (e) {
@@ -614,18 +580,14 @@ MessageComposer.prototype.onKeyEvent = function (e) {
currentSelected.removeClass('composer_autocomplete_option_active');
if (nextWrap) {
$(nextWrap).find('a').addClass('composer_autocomplete_option_active');
- if (!Config.Mobile) {
- scrollToNode(this.autoCompleteEl[0], nextWrap, this.autoCompleteScrollerEl);
- }
+ this.scroller.scrollToNode(nextWrap);
return cancelEvent(e);
}
}
var childNodes = this.autoCompleteEl[0].childNodes;
var nextWrap = childNodes[next ? 0 : childNodes.length - 1];
- if (!Config.Mobile) {
- scrollToNode(this.autoCompleteEl[0], nextWrap, this.autoCompleteScrollerEl);
- }
+ this.scroller.scrollToNode(nextWrap);
$(nextWrap).find('a').addClass('composer_autocomplete_option_active');
return cancelEvent(e);
@@ -714,7 +676,7 @@ MessageComposer.prototype.restoreSelection = function () {
-MessageComposer.prototype.checkAutocomplete = function () {
+MessageComposer.prototype.checkAutocomplete = function (forceFull) {
if (Config.Mobile) {
return false;
}
@@ -730,7 +692,9 @@ MessageComposer.prototype.checkAutocomplete = function () {
var value = textarea.value;
}
- value = value.substr(0, pos);
+ if (!forceFull) {
+ value = value.substr(0, pos);
+ }
var matches = value.match(this.autoCompleteRegEx);
if (matches) {
@@ -1096,15 +1060,7 @@ MessageComposer.prototype.focus = function () {
MessageComposer.prototype.renderSuggestions = function (html) {
this.autoCompleteEl.html(html.join(''));
this.autoCompleteWrapEl.show();
-
- var self = this;
- if (!Config.Mobile) {
- self.autoCompleteScrollerEl.nanoScroller({scroll: 'top'});
- setTimeout(function () {
- self.autoCompleteScrollerEl.nanoScroller();
- }, 100);
- }
-
+ this.scroller.reinit();
this.updatePosition();
this.autocompleteShown = true;
}
@@ -1161,7 +1117,7 @@ MessageComposer.prototype.showCommandsSuggestions = function (commands) {
for (i = 0; i < count; i++) {
command = commands[i];
- html.push('
' + encodeEntities(command.value) + '' + encodeEntities(command.description) + '');
+ html.push('
' + encodeEntities(command.value) + '' + command.rDescription + '');
}
this.renderSuggestions(html);
@@ -1182,14 +1138,13 @@ MessageComposer.prototype.showCommandsSuggestions = function (commands) {
MessageComposer.prototype.updatePosition = function () {
var offset = (this.richTextareaEl || this.textareaEl).offset();
var width = (this.richTextareaEl || this.textareaEl).outerWidth();
- var contentHeight = this.autoCompleteEl[0].firstChild.clientHeight * this.autoCompleteEl[0].childNodes.length;
- var height = Math.min(180, contentHeight);
+ var height = this.scroller.updateHeight();
this.autoCompleteWrapEl.css({
top: offset.top - height,
left: offset.left,
- width: width - 2,
- height: height
+ width: width - 2
});
+ this.scroller.update();
}
MessageComposer.prototype.hideSuggestions = function () {
@@ -1202,3 +1157,83 @@ MessageComposer.prototype.resetTyping = function () {
this.lastLength = 0;
}
+
+
+function Scroller(content, options) {
+ options = options || {};
+ var classPrefix = options.classPrefix || 'scroller';
+
+ this.content = $(content);
+ this.content.wrap('
');
+
+ this.scrollable = $(this.content[0].parentNode);
+ this.scroller = $(this.scrollable[0].parentNode);
+ this.wrap = $(this.scroller[0].parentNode);
+
+ this.useNano = options.nano !== undefined ? options.nano : !Config.Mobile;
+ this.maxHeight = options.maxHeight;
+
+ if (this.useNano) {
+ this.scrollable.addClass('nano-content');
+ this.scroller.addClass('nano');
+ this.scroller.nanoScroller({preventPageScrolling: true, tabIndex: -1});
+ } else {
+ if (this.maxHeight) {
+ this.wrap.css({maxHeight: this.maxHeight});
+ }
+ }
+ this.updateHeight();
+}
+
+Scroller.prototype.update = function () {
+ if (this.useNano) {
+ $(this.scroller).nanoScroller();
+ }
+}
+
+Scroller.prototype.reinit = function () {
+ this.scrollTo(0);
+ if (this.useNano) {
+ setTimeout((function () {
+ this.updateHeight();
+ }).bind(this), 100)
+ }
+}
+
+Scroller.prototype.updateHeight = function () {
+ var height;
+ if (this.maxHeight) {
+ var contentHeight = this.content[0].offsetHeight;
+ height = Math.min(this.maxHeight, contentHeight);
+ this.wrap.css({height: height});
+ } else {
+ height = this.scroller[0].offsetHeight;
+ }
+ $(this.scroller).nanoScroller();
+ return height;
+}
+
+
+Scroller.prototype.scrollTo = function (scrollTop) {
+ this.scrollable[0].scrollTop = scrollTop;
+ if (this.useNano) {
+ $(this.scroller).nanoScroller({flash: true});
+ }
+}
+
+Scroller.prototype.scrollToNode = function (node) {
+ node = node[0] || node;
+ var elTop = node.offsetTop - 15,
+ elHeight = node.offsetHeight + 30,
+ scrollTop = this.scrollable[0].scrollTop,
+ viewportHeight = this.scrollable[0].clientHeight;
+
+ if (scrollTop > elTop) { // we are below the node to scroll
+ this.scrollTo(elTop);
+ }
+ else if (scrollTop < elTop + elHeight - viewportHeight) { // we are over the node to scroll
+ this.scrollTo(elTop + elHeight - viewportHeight);
+ }
+}
+
+
diff --git a/app/js/services.js b/app/js/services.js
index 1988eb45..f0611a90 100755
--- a/app/js/services.js
+++ b/app/js/services.js
@@ -1055,7 +1055,12 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
});
if (historiesStorage[peerID] === undefined) {
- historiesStorage[peerID] = {count: null, history: [dialog.top_message], pending: []}
+ var historyStorage = {count: null, history: [dialog.top_message], pending: []};
+ historiesStorage[peerID] = historyStorage;
+ var message = getMessage(dialog.top_message);
+ if (mergeReplyKeyboard(historyStorage, message)) {
+ $rootScope.$broadcast('history_reply_markup', {peerID: peerID});
+ }
}
NotificationsManager.savePeerSettings(peerID, dialog.notify_settings);
@@ -1291,7 +1296,6 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}
function getReplyKeyboard (peerID) {
- console.log('get', historiesStorage[peerID]);
return (historiesStorage[peerID] || {}).reply_markup || false;
}
@@ -2413,6 +2417,10 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}
function wrapReplyMarkup (replyMarkup) {
+ if (!replyMarkup ||
+ replyMarkup._ == 'replyKeyboardHide') {
+ return false;
+ }
if (replyMarkup.wrapped) {
return replyMarkup;
}
@@ -2422,6 +2430,10 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
markupButton.rText = RichTextProcessor.wrapRichText(markupButton.text, {noLinks: true, noLinebreaks: true});
})
})
+
+ if (nextRandomInt(1)) {
+ replyMarkup.rows = replyMarkup.rows.slice(0, 2);
+ }
return replyMarkup;
}
diff --git a/app/less/app.less b/app/less/app.less
index e6f8c976..3aba2e46 100644
--- a/app/less/app.less
+++ b/app/less/app.less
@@ -2062,11 +2062,14 @@ a.im_message_fwd_photo {
.im_send_field_wkeyboard {
.im_send_buttons_wrap {
- display: none;
+ // display: none;
}
}
.reply_markup_wrap {
- margin: 5px -2px 0;
+ margin: 7px -2px 0;
+}
+.reply_markup_scrollable_wrap.has-scrollbar .reply_markup_row {
+ margin-right: 6px;
}
.reply_markup_button_wrap {
display: inline-block;
@@ -2075,11 +2078,12 @@ a.im_message_fwd_photo {
.reply_markup_button {
display: block;
width: 100%;
- background: #EEE;
+ background: #EFEFEF;
margin: 0;
}
.reply_markup_button:hover {
- background: #DDD;
+ // background: #DDD;
+ background: #f2f6fa;
}
.reply_markup_button_w1 {width: 100%;}
.reply_markup_button_w2 {width: 50%;}
@@ -2094,6 +2098,8 @@ a.im_message_fwd_photo {
.reply_markup_button_w11 {width: 9.09090909%;}
.reply_markup_button_w12 {width: 8.33333333%;}
+
+
.im_history_not_selected,
.im_history_empty {
visibility: hidden;
@@ -2360,14 +2366,11 @@ img.img_fullsize {
.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 {
+.composer_emoji_tooltip_scrollable_container {
height: 174px;
position: relative;
}
.composer_emoji_tooltip_content {
- /*position: relative;*/
- /*overflow: hidden;
- overflow-y: auto;*/
padding-right: 8px;
outline: 0!important;
}
@@ -2568,6 +2571,9 @@ a.composer_command_option:hover .composer_command_desc,
a.composer_command_option.composer_autocomplete_option_active .composer_command_desc {
color: #698192;
}
+.composer_command_desc .emoji {
+ vertical-align: text-bottom;
+}
.composer_stickerset_title {
@@ -2654,6 +2660,57 @@ a.composer_command_option.composer_autocomplete_option_active .composer_command_
}
}
+.composer_command_btn {
+ display: block;
+ position: absolute;
+ right: 23px;
+ top: 2px;
+ cursor: pointer;
+ padding: 0;
+
+ width: 22px;
+ height: 22px;
+ margin-top: 1px;
+}
+.icon-slash {
+ display: inline-block;
+ width: 22px;
+ height: 22px;
+ vertical-align: top;
+ opacity: 0.8;
+
+ .image-2x('../img/icons/General.png', 40px, 778px);
+ background-position: -9px -335px;
+}
+
+.composer_keyboard_btn {
+ display: block;
+ position: absolute;
+ right: 28px;
+ top: -2px;
+ cursor: pointer;
+ padding: 0;
+
+ width: 22px;
+ height: 22px;
+ margin-top: 1px;
+}
+.icon-hide-keyboard {
+ display: inline-block;
+ width: 16px;
+ height: 16px;
+ border: 2px solid #BBB;
+ border-top: 0;
+ border-left: 0;
+ .transform(rotate(45deg));
+ vertical-align: top;
+ opacity: 0.8;
+}
+.composer_keyboard_btn:hover .icon-hide-keyboard {
+ opacity: 1.0;
+}
+
+
.error_modal_window {
.modal-dialog {
max-width: 350px;
diff --git a/app/less/desktop.less b/app/less/desktop.less
index 8cc9800f..17bd2170 100644
--- a/app/less/desktop.less
+++ b/app/less/desktop.less
@@ -702,6 +702,24 @@ a.footer_link.active:active {
}
}
+.reply_markup_scrollable_container {
+ .nano > .nano-pane {
+ background: rgba(137, 160, 179, 0.1);
+ right: 2px;
+ width: 3px;
+ top: 2px;
+ bottom: 2px;
+ .rounded(1px);
+
+ & > .nano-slider {
+ .rounded(1px);
+ background: #d1d1d1;
+ background: rgba(137, 160, 179, 0.5);
+ margin: 0;
+ }
+ }
+}
+
.im_history {
&_no_dialogs_wrap {
margin: 122px 170px 60px;
@@ -1396,13 +1414,104 @@ a.im_panel_peer_photo .peer_initials {
}
.im_send_field_wkeyboard {
+
+ a {
+ &.im_panel_peer_photo,
+ &.im_panel_own_photo {
+ display: none;
+ }
+ }
+
+ .im_send_field_wrap {
+ margin-bottom: 0;
+ }
+
.composer {
&_rich_textarea,
&_textarea {
min-height: 25px;
padding-right: 25px;
}
+
+ &_emoji_insert_btn {
+ top: 0;
+ right: 0px;
+ margin-top: -3px;
+ }
+
+ &_emoji_panel {
+ display: none;
+ }
+ }
+
+ .im_submit {
+ position: absolute;
+ top: 0;
+ left: 100%;
+ margin: 0 0 0 15px;
}
+ .im_media_attach {
+ position: absolute;
+ top: -6px;
+ left: -43px;
+ width: 19px;
+ height: 24px;
+ }
+
+ .icon-camera {
+ display: inline-block;
+ width: 19px;
+ height: 23px;
+ vertical-align: text-top;
+ opacity: 0.8;
+ margin-top: -1px;
+
+ .image-2x('../img/icons/IconsetW.png', 42px, 1171px);
+ background-position: -12px -68px;
+ }
+
+ .im_media_attach {
+ &:hover .icon-camera,
+ &:active .icon-camera {
+ background-position: -12px -100px;
+ opacity: 1;
+ }
+ }
+
+ .im_attach {
+ display: none;
+ position: absolute;
+ top: 0;
+ right: 100%;
+ margin: 0;
+ margin-right: 45px;
+ margin-top: 1px;
+ }
+
+ .icon-emoji {
+ display: inline-block;
+ width: 22px;
+ height: 22px;
+ vertical-align: text-top;
+ opacity: 1;
+ margin: 0;
+
+ .image-2x('../img/icons/IconsetW.png', 42px, 1171px);
+ background-position: -10px -771px;
+ }
+
+ .composer_emoji_insert_btn:active .icon-emoji,
+ .is_1x .composer_emoji_insert_btn:active .icon-emoji,
+ .composer_emoji_insert_btn.composer_emoji_insert_btn_on .icon-emoji,
+ .is_1x .composer_emoji_insert_btn.composer_emoji_insert_btn_on .icon-emoji {
+ background-position: -10px -803px;
+ }
+
+ .im_send_dropbox_wrap {
+ display: none;
+ }
+
+
}
/* Peer modals */
diff --git a/app/partials/desktop/im.html b/app/partials/desktop/im.html
index a87a7b81..705370b6 100644
--- a/app/partials/desktop/im.html
+++ b/app/partials/desktop/im.html
@@ -158,7 +158,7 @@