Merge branch 'master' into voice_recorder
This commit is contained in:
commit
c24bfc640d
1
app/img/Telegram.svg
Normal file
1
app/img/Telegram.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 5.2 KiB |
@ -7,6 +7,12 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var extraModules = [];
|
||||
if (Config.Modes.animations) {
|
||||
extraModules.push('ngAnimate');
|
||||
}
|
||||
|
||||
|
||||
// Declare app level module which depends on filters, and services
|
||||
angular.module('myApp', [
|
||||
'ngRoute',
|
||||
@ -24,7 +30,7 @@ angular.module('myApp', [
|
||||
PRODUCTION_ONLY_END*/
|
||||
'myApp.directives',
|
||||
'myApp.controllers'
|
||||
]).
|
||||
].concat(extraModules)).
|
||||
config(['$locationProvider', '$routeProvider', '$compileProvider', 'StorageProvider', function($locationProvider, $routeProvider, $compileProvider, StorageProvider) {
|
||||
|
||||
$compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|file|blob|filesystem|chrome-extension|app):|data:image\//);
|
||||
|
@ -1058,6 +1058,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
$scope.selectedReply = selectedReply;
|
||||
$scope.selectedCancel = selectedCancel;
|
||||
$scope.selectedFlush = selectedFlush;
|
||||
$scope.selectInlineBot = selectInlineBot;
|
||||
|
||||
$scope.startBot = startBot;
|
||||
$scope.cancelBot = cancelBot;
|
||||
@ -1195,7 +1196,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
$scope.historyState.typing.splice(0, $scope.historyState.typing.length);
|
||||
$scope.$broadcast('ui_peer_change');
|
||||
$scope.$broadcast('ui_history_change');
|
||||
safeReplaceObject($scope.state, {loaded: true, empty: !peerHistory.messages.length});
|
||||
safeReplaceObject($scope.state, {loaded: true, empty: !peerHistory.messages.length, mayBeHasMore: true});
|
||||
|
||||
updateBotActions();
|
||||
updateChannelActions();
|
||||
@ -1299,14 +1300,14 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
return;
|
||||
}
|
||||
lessPending = false;
|
||||
lessActive = true;
|
||||
$scope.state.lessActive = lessActive = true;
|
||||
|
||||
var curJump = jump,
|
||||
curLessJump = ++lessJump,
|
||||
limit = 0,
|
||||
backLimit = 20;
|
||||
AppMessagesManager.getHistory($scope.curDialog.peerID, minID, limit, backLimit).then(function (historyResult) {
|
||||
lessActive = false;
|
||||
$scope.state.lessActive = lessActive = false;
|
||||
if (curJump != jump || curLessJump != lessJump) return;
|
||||
|
||||
var i, id;
|
||||
@ -1347,7 +1348,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
return;
|
||||
}
|
||||
morePending = false;
|
||||
moreActive = true;
|
||||
$scope.state.moreActive = moreActive = true;
|
||||
|
||||
var curJump = jump,
|
||||
curMoreJump = ++moreJump,
|
||||
@ -1358,7 +1359,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
: AppMessagesManager.getHistory($scope.curDialog.peerID, maxID, limit);
|
||||
|
||||
getMessagesPromise.then(function (historyResult) {
|
||||
moreActive = false;
|
||||
$scope.state.moreActive = moreActive = false;
|
||||
if (curJump != jump || curMoreJump != moreJump) return;
|
||||
|
||||
angular.forEach(historyResult.history, function (id) {
|
||||
@ -1405,9 +1406,9 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
limit = 10;
|
||||
}
|
||||
|
||||
moreActive = false;
|
||||
$scope.state.moreActive = moreActive = false;
|
||||
morePending = false;
|
||||
lessActive = false;
|
||||
$scope.state.lessActive = lessActive = false;
|
||||
lessPending = false;
|
||||
|
||||
var prerenderedLen = peerHistory.messages.length;
|
||||
@ -1550,23 +1551,31 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
|
||||
var target = $event.target;
|
||||
while (target) {
|
||||
if (target.className.indexOf('im_message_outer_wrap') != -1) {
|
||||
if (target instanceof SVGElement) {
|
||||
target = target.parentNode;
|
||||
continue;
|
||||
}
|
||||
if (target.className && target.className.indexOf('im_message_outer_wrap') != -1) {
|
||||
if (Config.Mobile) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (target.className &&
|
||||
target.className.indexOf('im_message_date') != -1) {
|
||||
if ($scope.historyState.canReply) {
|
||||
selectedReply(messageID);
|
||||
} else {
|
||||
selectedForward(messageID);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (Config.Mobile &&
|
||||
target.className &&
|
||||
target.className.indexOf('im_message_body') != -1) {
|
||||
break;
|
||||
}
|
||||
if (target.tagName == 'A' ||
|
||||
target.onclick ||
|
||||
target.getAttribute('ng-click')) {
|
||||
return false;
|
||||
}
|
||||
var events = $._data(target, 'events');
|
||||
if (events && (events.click || events.mousedown)) {
|
||||
if (target.tagName == 'A' || hasOnlick(target)) {
|
||||
return false;
|
||||
}
|
||||
target = target.parentNode;
|
||||
@ -1651,6 +1660,11 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
$scope.$broadcast('messages_select');
|
||||
}
|
||||
|
||||
function selectInlineBot (botID, $event) {
|
||||
$scope.$broadcast('inline_bot_select', botID);
|
||||
return cancelEvent($event);
|
||||
}
|
||||
|
||||
function selectedCancel (noBroadcast) {
|
||||
$scope.selectedMsgs = {};
|
||||
$scope.selectedCount = 0;
|
||||
@ -2069,7 +2083,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, RichTextProcessor) {
|
||||
.controller('AppImSendController', function ($scope, $timeout, MtpApiManager, Storage, AppProfileManager, AppChatsManager, AppUsersManager, AppPeersManager, AppDocsManager, AppMessagesManager, AppInlineBotsManager, MtpApiFileManager, RichTextProcessor) {
|
||||
|
||||
$scope.$watch('curDialog.peer', resetDraft);
|
||||
$scope.$on('user_update', angular.noop);
|
||||
@ -2091,6 +2105,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
$scope.$watch('draftMessage.files', onFilesSelected);
|
||||
$scope.$watch('draftMessage.sticker', onStickerSelected);
|
||||
$scope.$watch('draftMessage.command', onCommandSelected);
|
||||
$scope.$watch('draftMessage.inlineResultID', onInlineResultSelected);
|
||||
|
||||
$scope.$on('history_reply_markup', function (e, peerData) {
|
||||
if (peerData.peerID == $scope.curDialog.peerID) {
|
||||
@ -2098,6 +2113,12 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$on('inline_bot_select', function (e, botID) {
|
||||
var bot = AppUsersManager.getUser(botID);
|
||||
$scope.draftMessage.text = '@' + bot.username + ' ';;
|
||||
$scope.$broadcast('ui_peer_draft', {focus: true});
|
||||
});
|
||||
|
||||
$scope.replyKeyboardToggle = replyKeyboardToggle;
|
||||
$scope.toggleSlash = toggleSlash;
|
||||
|
||||
@ -2250,6 +2271,9 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
$scope.draftMessage.text = '';
|
||||
$scope.$broadcast('ui_peer_draft');
|
||||
}
|
||||
|
||||
delete $scope.draftMessage.inlineProgress;
|
||||
$scope.$broadcast('inline_results', false);
|
||||
}
|
||||
|
||||
function applyDraftAttachment (e, attachment) {
|
||||
@ -2394,6 +2418,60 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
Storage.remove('draft' + $scope.curDialog.peerID);
|
||||
// console.log(dT(), 'draft delete', 'draft' + $scope.curDialog.peerID);
|
||||
}
|
||||
checkInlinePattern(newVal);
|
||||
}
|
||||
|
||||
var inlineUsernameRegex = /^@([a-zA-Z\d_]{1,32})( | )([\s\S]*)$/;
|
||||
var getInlineResultsTO = false;
|
||||
var jump = 0;
|
||||
|
||||
function checkInlinePattern (message) {
|
||||
if (getInlineResultsTO) {
|
||||
$timeout.cancel(getInlineResultsTO);
|
||||
}
|
||||
var curJump = ++jump;
|
||||
if (!message || !message.length) {
|
||||
delete $scope.draftMessage.inlineProgress;
|
||||
$scope.$broadcast('inline_results', false);
|
||||
return;
|
||||
}
|
||||
var matches = message.match(inlineUsernameRegex);
|
||||
if (!matches) {
|
||||
delete $scope.draftMessage.inlineProgress;
|
||||
$scope.$broadcast('inline_results', false);
|
||||
return;
|
||||
}
|
||||
var username = matches[1];
|
||||
$scope.draftMessage.inlineProgress = true;
|
||||
AppPeersManager.resolveInlineMention(username).then(function (inlineBot) {
|
||||
if (curJump != jump) {
|
||||
return;
|
||||
}
|
||||
$scope.$broadcast('inline_placeholder', {
|
||||
prefix: '@' + username + matches[2],
|
||||
placeholder: inlineBot.placeholder
|
||||
});
|
||||
if (getInlineResultsTO) {
|
||||
$timeout.cancel(getInlineResultsTO);
|
||||
}
|
||||
getInlineResultsTO = $timeout(function () {
|
||||
AppInlineBotsManager.getInlineResults(inlineBot.id, matches[3], '').then(function (botResults) {
|
||||
getInlineResultsTO = false;
|
||||
if (curJump != jump) {
|
||||
return;
|
||||
}
|
||||
botResults.text = message;
|
||||
$scope.$broadcast('inline_results', botResults);
|
||||
delete $scope.draftMessage.inlineProgress;
|
||||
}, function () {
|
||||
$scope.$broadcast('inline_results', false);
|
||||
delete $scope.draftMessage.inlineProgress;
|
||||
});
|
||||
}, 500);
|
||||
}, function () {
|
||||
$scope.$broadcast('inline_results', false);
|
||||
delete $scope.draftMessage.inlineProgress;
|
||||
});
|
||||
}
|
||||
|
||||
function onTyping () {
|
||||
@ -2455,7 +2533,6 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
fwdsSend();
|
||||
}
|
||||
delete $scope.draftMessage.sticker;
|
||||
resetDraft();
|
||||
}
|
||||
|
||||
function onCommandSelected (command) {
|
||||
@ -2467,6 +2544,25 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
delete $scope.draftMessage.sticker;
|
||||
delete $scope.draftMessage.text;
|
||||
delete $scope.draftMessage.command;
|
||||
delete $scope.draftMessage.inlineResultID;
|
||||
$scope.$broadcast('ui_message_send');
|
||||
$scope.$broadcast('ui_peer_draft');
|
||||
}
|
||||
|
||||
function onInlineResultSelected (qID) {
|
||||
if (!qID) {
|
||||
return;
|
||||
}
|
||||
var options = {
|
||||
replyToMsgID: $scope.draftMessage.replyToMessage && $scope.draftMessage.replyToMessage.mid
|
||||
};
|
||||
AppInlineBotsManager.sendInlineResult($scope.curDialog.peerID, qID, options);
|
||||
fwdsSend();
|
||||
resetDraft();
|
||||
delete $scope.draftMessage.sticker;
|
||||
delete $scope.draftMessage.text;
|
||||
delete $scope.draftMessage.command;
|
||||
delete $scope.draftMessage.inlineResultID;
|
||||
$scope.$broadcast('ui_message_send');
|
||||
$scope.$broadcast('ui_peer_draft');
|
||||
}
|
||||
@ -4654,11 +4750,14 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
.controller('StickersetModalController', function ($scope, $rootScope, $modalInstance, MtpApiManager, RichTextProcessor, AppStickersManager, AppDocsManager, AppMessagesManager, LocationParamsService) {
|
||||
$scope.slice = {limit: 20, limitDelta: 20};
|
||||
|
||||
var fullSet;
|
||||
|
||||
AppStickersManager.getStickerset($scope.inputStickerset).then(function (result) {
|
||||
$scope.$broadcast('ui_height');
|
||||
$scope.stickersetLoaded = true;
|
||||
fullSet = result;
|
||||
$scope.stickerset = result.set;
|
||||
$scope.stickersetInstalled = result.installed;
|
||||
$scope.stickersetInstalled = result.set.pFlags.installed == true;
|
||||
$scope.documents = result.documents;
|
||||
|
||||
$scope.stickerEmojis = {};
|
||||
@ -4673,7 +4772,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
|
||||
});
|
||||
|
||||
$scope.toggleInstalled = function (installed) {
|
||||
AppStickersManager.installStickerset($scope.stickerset, !installed).then(function () {
|
||||
AppStickersManager.installStickerset(fullSet, !installed).then(function () {
|
||||
$scope.stickersetInstalled = installed;
|
||||
})
|
||||
};
|
||||
|
@ -1099,6 +1099,7 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
historyEl = $('.im_history', element)[0],
|
||||
scrollableWrap = $('.im_history_scrollable_wrap', element)[0],
|
||||
scrollable = $('.im_history_scrollable', element)[0],
|
||||
emptyWrapEl = $('.im_history_empty_wrap', element)[0],
|
||||
bottomPanelWrap = $('.im_bottom_panel_wrap', element)[0],
|
||||
sendFormWrap = $('.im_send_form_wrap', element)[0],
|
||||
headWrap = $('.tg_page_head')[0],
|
||||
@ -1412,7 +1413,7 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
$(historyMessagesEl).css({marginTop: 0});
|
||||
var marginTop = scrollableWrap.offsetHeight
|
||||
- historyMessagesEl.offsetHeight
|
||||
- 20
|
||||
- emptyWrapEl.offsetHeight
|
||||
- (Config.Mobile ? 0 : 39);
|
||||
|
||||
if (historyMessagesEl.offsetHeight > 0 && marginTop > 0) {
|
||||
@ -1429,8 +1430,7 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
|
||||
})
|
||||
|
||||
.directive('mySendForm', function (_, $window, $compile, $modalStack, $http, $interpolate, Storage, AppStickersManager, AppDocsManager, ErrorService, shouldFocusOnInteraction) {
|
||||
|
||||
.directive('mySendForm', function (_, $timeout, $compile, $modalStack, $http, $interpolate, Storage, AppStickersManager, AppDocsManager, ErrorService, AppInlineBotsManager, shouldFocusOnInteraction) {
|
||||
return {
|
||||
link: link,
|
||||
scope: {
|
||||
@ -1497,6 +1497,11 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$on('stickers_changed', function () {
|
||||
emojiTooltip.onStickersChanged();
|
||||
});
|
||||
|
||||
|
||||
var composerEmojiPanel;
|
||||
if (emojiPanel) {
|
||||
composerEmojiPanel = new EmojiPanel(emojiPanel, {
|
||||
@ -1506,9 +1511,6 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
});
|
||||
}
|
||||
|
||||
var peerPhotoCompiled = $compile('<span class="composer_user_photo" my-peer-photolink="peerID" img-class="composer_user_photo"></span>');
|
||||
var cachedPeerPhotos = {};
|
||||
|
||||
var composer = new MessageComposer(messageField, {
|
||||
onTyping: function () {
|
||||
$scope.$emit('ui_typing');
|
||||
@ -1516,21 +1518,17 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
getSendOnEnter: function () {
|
||||
return sendOnEnter;
|
||||
},
|
||||
getPeerImage: function (element, peerID, noReplace) {
|
||||
if (cachedPeerPhotos[peerID] && !noReplace) {
|
||||
element.replaceWith(cachedPeerPhotos[peerID]);
|
||||
return;
|
||||
}
|
||||
dropdownDirective: function (element, callback) {
|
||||
var scope = $scope.$new(true);
|
||||
scope.peerID = peerID;
|
||||
peerPhotoCompiled(scope, function (clonedElement) {
|
||||
cachedPeerPhotos[peerID] = clonedElement;
|
||||
var clonedElement = $compile('<div><div my-composer-dropdown></div></div>')(scope, function (clonedElement, scope) {
|
||||
element.replaceWith(clonedElement);
|
||||
callback(scope, clonedElement);
|
||||
});
|
||||
},
|
||||
mentions: $scope.mentions,
|
||||
commands: $scope.commands,
|
||||
onMessageSubmit: onMessageSubmit,
|
||||
onInlineResultSend: onInlineResultSend,
|
||||
onFilePaste: onFilePaste,
|
||||
onCommandSend: function (command) {
|
||||
$scope.$apply(function () {
|
||||
@ -1544,6 +1542,21 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
$(richTextarea).on('keydown keyup', updateHeight);
|
||||
}
|
||||
|
||||
$scope.$on('inline_results', function (e, inlineResults) {
|
||||
if (inlineResults) {
|
||||
var w = ((richTextarea || messageField).offsetWidth || 382) - 2;
|
||||
var h = 80;
|
||||
AppInlineBotsManager.regroupWrappedResults(inlineResults.results, w, h);
|
||||
setZeroTimeout(function () {
|
||||
composer.setInlineSuggestions(inlineResults);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$on('inline_placeholder', function(e, data) {
|
||||
composer.setInlinePlaceholder(data.prefix, data.placeholder);
|
||||
});
|
||||
|
||||
fileSelects.on('change', function () {
|
||||
var self = this;
|
||||
$scope.$apply(function () {
|
||||
@ -1659,6 +1672,12 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
return cancelEvent(e);
|
||||
}
|
||||
|
||||
function onInlineResultSend (qID) {
|
||||
$scope.$apply(function () {
|
||||
$scope.draftMessage.inlineResultID = qID;
|
||||
});
|
||||
}
|
||||
|
||||
function updateValue () {
|
||||
if (richTextarea) {
|
||||
composer.onChange();
|
||||
@ -2063,7 +2082,7 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
|
||||
})
|
||||
|
||||
.directive('myLoadGif', function(AppDocsManager) {
|
||||
.directive('myLoadGif', function(AppDocsManager, $timeout) {
|
||||
|
||||
return {
|
||||
link: link,
|
||||
@ -2082,6 +2101,15 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
|
||||
$scope.isActive = false;
|
||||
|
||||
// Demo
|
||||
// $scope.document.progress = {enabled: true, percent: 30};
|
||||
// $timeout(function () {
|
||||
// $scope.document.progress.percent = 60;
|
||||
// }, 3000);
|
||||
// $timeout(function () {
|
||||
// $scope.document.progress.percent = 100;
|
||||
// }, 10000);
|
||||
|
||||
$scope.toggle = function (e) {
|
||||
if (e && checkClick(e, true)) {
|
||||
AppDocsManager.saveDocFile($scope.document.id);
|
||||
@ -2092,6 +2120,16 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
onContentLoaded(function () {
|
||||
$scope.isActive = !$scope.isActive;
|
||||
$scope.$emit('ui_height');
|
||||
|
||||
var video = $('video', element)[0];
|
||||
if (video) {
|
||||
if (!$scope.isActive) {
|
||||
video.pause();
|
||||
video.currentTime = 0;
|
||||
} else {
|
||||
video.play();
|
||||
}
|
||||
}
|
||||
})
|
||||
return;
|
||||
}
|
||||
@ -2105,8 +2143,9 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
downloadPromise = AppDocsManager.downloadDoc($scope.document.id);
|
||||
|
||||
downloadPromise.then(function () {
|
||||
$scope.isActive = true;
|
||||
$scope.$emit('ui_height');
|
||||
$timeout(function () {
|
||||
$scope.isActive = true;
|
||||
}, 200);
|
||||
})
|
||||
}
|
||||
|
||||
@ -2330,8 +2369,8 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
|
||||
var src = 'https://maps.googleapis.com/maps/api/staticmap?sensor=false¢er=' + $scope.point['lat'] + ',' + $scope.point['long'] + '&zoom=15&size='+width+'x'+height+'&scale=2&key=' + apiKey;
|
||||
|
||||
ExternalResourcesManager.downloadImage(src).then(function (url) {
|
||||
element.attr('src', url);
|
||||
ExternalResourcesManager.downloadByURL(src).then(function (url) {
|
||||
element.attr('src', url.valueOf());
|
||||
});
|
||||
}
|
||||
|
||||
@ -2831,7 +2870,7 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
}
|
||||
};
|
||||
|
||||
if (element[0].tagName == 'A') {
|
||||
if (element[0].tagName == 'A' && !hasOnlick(element[0])) {
|
||||
element.on('click', function () {
|
||||
if (peerID > 0) {
|
||||
AppUsersManager.openUser(peerID, override);
|
||||
@ -3317,44 +3356,67 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
})
|
||||
|
||||
.directive('myArcProgress', function () {
|
||||
var html = '<svg class="progress-arc" viewPort="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg"><circle class="progress-arc-circle" fill="transparent" stroke-dashoffset="0"></circle><circle class="progress-arc-bar" fill="transparent" stroke-dashoffset="0"></circle></svg>';
|
||||
var html =
|
||||
'<svg class="progress-arc" viewPort="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">\
|
||||
<defs>\
|
||||
<linearGradient id="grad_intermediate%id%" x1="0%" y1="0%" x2="100%" y2="0%">\
|
||||
<stop offset="0%" class="stop0" />\
|
||||
<stop offset="60%" class="stop60" />\
|
||||
<stop offset="100%" class="stop100"/>\
|
||||
</linearGradient>\
|
||||
</defs>\
|
||||
<circle class="progress-arc-bar"></circle>\
|
||||
</svg>';
|
||||
|
||||
function updateProgress (bar, progress, fullLen) {
|
||||
progress = Math.max(0.0, Math.min(progress, 1.0));
|
||||
var minProgress = 0.2;
|
||||
progress = minProgress + (1 - minProgress) * progress;
|
||||
bar.css({strokeDasharray: (progress * fullLen) + ', ' + ((1 - progress) * fullLen)});
|
||||
}
|
||||
|
||||
var num = 0;
|
||||
|
||||
return {
|
||||
scope: {
|
||||
progress: '=myArcProgress'
|
||||
},
|
||||
link: function ($scope, element, attrs) {
|
||||
element
|
||||
.html(html)
|
||||
.addClass('progress-arc-wrap');
|
||||
|
||||
var svgEl = element[0].firstChild;
|
||||
var circle = $('.progress-arc-circle', element);
|
||||
var bar = $('.progress-arc-bar', element);
|
||||
|
||||
var width = attrs.width || 40;
|
||||
var radius = width * 0.86;
|
||||
var stroke = width * 0.14;
|
||||
var intermediate = !attrs.myArcProgress;
|
||||
var width = attrs.width || element.width() || 40;
|
||||
var stroke = attrs.stroke || (width / 2 * 0.14);
|
||||
var center = width / 2;
|
||||
var radius = center - (stroke / 2);
|
||||
|
||||
$(svgEl).attr('width', width);
|
||||
$(svgEl).attr('height', width);
|
||||
circle.attr('cx', center);
|
||||
circle.attr('cy', center);
|
||||
circle.attr('r', radius);
|
||||
circle.css({strokeWidth: stroke});
|
||||
// Doesn't work without unique id for every gradient
|
||||
var curNum = ++num;
|
||||
|
||||
bar.attr('cx', center);
|
||||
bar.attr('cy', center);
|
||||
bar.attr('r', radius);
|
||||
bar.css({strokeWidth: stroke});
|
||||
element
|
||||
.html(html.replace('%id%', curNum))
|
||||
.addClass('progress-arc-wrap')
|
||||
.addClass(intermediate ? 'progress-arc-intermediate' : 'progress-arc-percent')
|
||||
.css({width: width, height: width});
|
||||
|
||||
$(element[0].firstChild)
|
||||
.attr('width', width)
|
||||
.attr('height', width);
|
||||
|
||||
var bar = $('.progress-arc-bar', element);
|
||||
bar
|
||||
.attr('cx', center)
|
||||
.attr('cy', center)
|
||||
.attr('r', radius)
|
||||
.css({strokeWidth: stroke});
|
||||
|
||||
var fullLen = 2 * Math.PI * radius;
|
||||
$scope.$watch('progress', function (newProgress) {
|
||||
var progress = newProgress / 100.0;
|
||||
progress = Math.max(0.0, Math.min(progress, 1.0));
|
||||
bar.css({strokeDasharray: (progress * fullLen) + ', ' + ((1 - progress) * fullLen)});
|
||||
});
|
||||
|
||||
if (intermediate) {
|
||||
updateProgress(bar, 0.3, fullLen);
|
||||
bar.css({stroke: 'url(#grad_intermediate' + curNum + ')'});
|
||||
} else {
|
||||
$scope.$watch('progress', function (newProgress) {
|
||||
updateProgress(bar, newProgress / 100.0, fullLen);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -3380,3 +3442,87 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
};
|
||||
|
||||
})
|
||||
|
||||
.directive('myComposerDropdown', function () {
|
||||
|
||||
return {
|
||||
templateUrl: templateUrl('composer_dropdown')
|
||||
}
|
||||
})
|
||||
|
||||
.directive('myEmojiSuggestions', function () {
|
||||
|
||||
return {
|
||||
link: function($scope, element, attrs) {
|
||||
$scope.$watchCollection('emojiCodes', function (codes) {
|
||||
// var codes = $scope.$eval(attrs.myEmojiSuggestions);
|
||||
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-w', iconSize, ' emoji-spritesheet-' + categoryIndex + '" style="background-position: -' + x + 'px -' + y + 'px;"></i><span class="composer_emoji_shortcut">:' + encodeEntities(emoticonData[1][0]) + ':</span></a></li>');
|
||||
}
|
||||
}
|
||||
// onContentLoaded(function () {
|
||||
element.html(html.join(''));
|
||||
console.log(dT(), 'emoji done');
|
||||
// });
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
})
|
||||
|
||||
.directive('myInlineResults', function (AppPhotosManager, ExternalResourcesManager, AppDocsManager) {
|
||||
|
||||
return {
|
||||
templateUrl: templateUrl('inline_results'),
|
||||
scope: {
|
||||
botResults: '=myInlineResults'
|
||||
},
|
||||
|
||||
link: function ($scope, element, attrs) {
|
||||
$scope.$watch('botResults.results', function (results) {
|
||||
angular.forEach(results, function (result) {
|
||||
if (result.thumb_url && !result.thumbUrl) {
|
||||
ExternalResourcesManager.downloadByURL(result.thumb_url).then(function (url) {
|
||||
result.thumbUrl = url;
|
||||
});
|
||||
}
|
||||
if (result.type == 'gif' && result.content_url && !result.contentUrl) {
|
||||
ExternalResourcesManager.downloadByURL(result.content_url).then(function (url) {
|
||||
result.contentUrl = url;
|
||||
});
|
||||
}
|
||||
if (result.type == 'gif' && result.document) {
|
||||
AppDocsManager.downloadDoc(result.document.id);
|
||||
}
|
||||
if (result.type == 'photo' && result.photo) {
|
||||
var photoSize = AppPhotosManager.choosePhotoSize(result.photo, result.thumbW, result.thumbH),
|
||||
dim = calcImageInBox(photoSize.w, photoSize.h, result.thumbW, result.thumbH);
|
||||
result.thumb = {
|
||||
width: dim.w,
|
||||
height: dim.h,
|
||||
location: photoSize.location,
|
||||
size: photoSize.size
|
||||
};
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -187,6 +187,9 @@ angular.module('myApp.filters', ['myApp.i18n'])
|
||||
.filter('formatSizeProgress', function ($filter, _) {
|
||||
var formatSizeFilter = $filter('formatSize');
|
||||
return function (progress) {
|
||||
if (!progress.total) {
|
||||
return '';
|
||||
}
|
||||
var done = formatSizeFilter(progress.done, true),
|
||||
doneParts = done.split(' '),
|
||||
total = formatSizeFilter(progress.total),
|
||||
|
@ -36,7 +36,9 @@ Config.Modes = {
|
||||
webcrypto: location.search.indexOf('webcrypto=0')== -1,
|
||||
packed: location.protocol == 'app:' || location.protocol == 'chrome-extension:',
|
||||
ios_standalone: window.navigator.standalone && navigator.userAgent.match(/iOS|iPhone|iPad/),
|
||||
chrome_packed: window.chrome && chrome.app && chrome.app.window && true || false
|
||||
chrome_packed: window.chrome && chrome.app && chrome.app.window && true || false,
|
||||
animations: true,
|
||||
memory_only: false
|
||||
};
|
||||
|
||||
Config.Navigator = {
|
||||
|
@ -384,11 +384,13 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
|
||||
}
|
||||
|
||||
function getFileStorage () {
|
||||
if (TmpfsFileStorage.isAvailable()) {
|
||||
return TmpfsFileStorage;
|
||||
}
|
||||
if (IdbFileStorage.isAvailable()) {
|
||||
return IdbFileStorage;
|
||||
if (!Config.Modes.memory_only) {
|
||||
if (TmpfsFileStorage.isAvailable()) {
|
||||
return TmpfsFileStorage;
|
||||
}
|
||||
if (IdbFileStorage.isAvailable()) {
|
||||
return IdbFileStorage;
|
||||
}
|
||||
}
|
||||
return MemoryFileStorage;
|
||||
}
|
||||
|
@ -963,10 +963,10 @@ angular.module('izhukov.utils', [])
|
||||
};
|
||||
})
|
||||
|
||||
.service('ExternalResourcesManager', function ($q, $http) {
|
||||
.service('ExternalResourcesManager', function ($q, $http, $sce) {
|
||||
var urlPromises = {};
|
||||
|
||||
function downloadImage (url) {
|
||||
function downloadByURL (url) {
|
||||
if (urlPromises[url] !== undefined) {
|
||||
return urlPromises[url];
|
||||
}
|
||||
@ -974,12 +974,18 @@ angular.module('izhukov.utils', [])
|
||||
return urlPromises[url] = $http.get(url, {responseType: 'blob', transformRequest: null})
|
||||
.then(function (response) {
|
||||
window.URL = window.URL || window.webkitURL;
|
||||
return window.URL.createObjectURL(response.data);
|
||||
var url = window.URL.createObjectURL(response.data);
|
||||
return $sce.trustAsResourceUrl(url);
|
||||
}, function (error) {
|
||||
if (!Config.modes.chrome_packed) {
|
||||
return $q.when($sce.trustAsResourceUrl(url));
|
||||
}
|
||||
return $q.reject(error);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
downloadImage: downloadImage
|
||||
downloadByURL: downloadByURL
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -60,6 +60,18 @@ function cancelEvent (event) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function hasOnlick (element) {
|
||||
if (element.onclick ||
|
||||
element.getAttribute('ng-click')) {
|
||||
return true;
|
||||
}
|
||||
var events = $._data(element, 'events');
|
||||
if (events && (events.click || events.mousedown)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getScrollWidth() {
|
||||
var outer = $('<div>').css({
|
||||
position: 'absolute',
|
||||
@ -289,7 +301,21 @@ function scrollToNode (scrollable, node, scroller) {
|
||||
}
|
||||
}
|
||||
|
||||
if (Config.Modes.animations &&
|
||||
typeof window.requestAnimationFrame == 'function') {
|
||||
window.onAnimationFrameCallback = function (cb) {
|
||||
return (function () {
|
||||
window.requestAnimationFrame(cb);
|
||||
});
|
||||
};
|
||||
} else {
|
||||
window.onAnimationFrameCallback = function (cb) {
|
||||
return cb;
|
||||
};
|
||||
}
|
||||
|
||||
function onContentLoaded (cb) {
|
||||
cb = onAnimationFrameCallback(cb);
|
||||
setZeroTimeout(cb);
|
||||
}
|
||||
|
||||
|
@ -253,6 +253,7 @@
|
||||
"conversation_media_video": "Video",
|
||||
"conversation_media_document": "Datei",
|
||||
"conversation_media_sticker": "Sticker",
|
||||
"conversation_media_gif": "GIF",
|
||||
"conversation_media_audio": "Audio",
|
||||
"conversation_media_location": "Standort",
|
||||
"conversation_media_contact": "Kontakt",
|
||||
@ -472,7 +473,9 @@
|
||||
"password_recover_submit": "Absenden",
|
||||
"login_controller_unknown_country": "Unbekannt",
|
||||
"message_forwarded_message": "Weitergeleitete Nachricht",
|
||||
"message_via_bot": "via {bot}",
|
||||
"message_forwarded_message_mobile": "Weitergeleitet von {from}, {date}",
|
||||
"message_forwarded_via_message_mobile": "Weitergeleitet von {from} via {bot}, {date}",
|
||||
"message_attach_audio_message": "Sprachnachricht",
|
||||
"message_attach_audio_play": "Abspielen",
|
||||
"message_attach_document_open": "Öffnen",
|
||||
|
@ -253,6 +253,7 @@
|
||||
"conversation_media_video": "Video",
|
||||
"conversation_media_document": "File",
|
||||
"conversation_media_sticker": "Sticker",
|
||||
"conversation_media_gif": "GIF",
|
||||
"conversation_media_audio": "Audio",
|
||||
"conversation_media_location": "Posizione",
|
||||
"conversation_media_contact": "Contatto",
|
||||
@ -472,7 +473,9 @@
|
||||
"password_recover_submit": "Invia",
|
||||
"login_controller_unknown_country": "Sconosciuto",
|
||||
"message_forwarded_message": "Messaggio inoltrato",
|
||||
"message_via_bot": "via {bot}",
|
||||
"message_forwarded_message_mobile": "Inoltrato da {from},{date}",
|
||||
"message_forwarded_via_message_mobile": "Inoltrato da {from} via {bot}, {date}",
|
||||
"message_attach_audio_message": "Nota vocale",
|
||||
"message_attach_audio_play": "Riproduci",
|
||||
"message_attach_document_open": "Apri",
|
||||
|
@ -253,6 +253,7 @@
|
||||
"conversation_media_video": "Vídeo",
|
||||
"conversation_media_document": "Arquivo",
|
||||
"conversation_media_sticker": "Sticker",
|
||||
"conversation_media_gif": "GIF",
|
||||
"conversation_media_audio": "Áudio",
|
||||
"conversation_media_location": "Localização",
|
||||
"conversation_media_contact": "Contato",
|
||||
@ -472,7 +473,9 @@
|
||||
"password_recover_submit": "Enviar",
|
||||
"login_controller_unknown_country": "Desconhecido",
|
||||
"message_forwarded_message": "Encaminhar mensagem",
|
||||
"message_via_bot": "via {bot}",
|
||||
"message_forwarded_message_mobile": "Encaminhado de {from}, {date}",
|
||||
"message_forwarded_via_message_mobile": "Encaminhado de {from} via {bot}, {date}",
|
||||
"message_attach_audio_message": "Mensagem de voz",
|
||||
"message_attach_audio_play": "Tocar",
|
||||
"message_attach_document_open": "Abrir",
|
||||
|
@ -251,8 +251,9 @@
|
||||
"conversation_you": "Вы",
|
||||
"conversation_media_photo": "Фотография",
|
||||
"conversation_media_video": "Видео",
|
||||
"conversation_media_document": "File",
|
||||
"conversation_media_document": "Файл",
|
||||
"conversation_media_sticker": "Стикер",
|
||||
"conversation_media_gif": "GIF",
|
||||
"conversation_media_audio": "Аудио",
|
||||
"conversation_media_location": "Местоположение",
|
||||
"conversation_media_contact": "Контакт",
|
||||
@ -357,7 +358,7 @@
|
||||
"head_edit_messages": "Редактировать сообщения",
|
||||
"head_media_photos": "Фотографии",
|
||||
"head_media_video": "Видео",
|
||||
"head_media_documents": "Files",
|
||||
"head_media_documents": "Файлы",
|
||||
"head_media_audio": "Голосовые сообщения",
|
||||
"head_about": "О приложении",
|
||||
"head_clear_all": "Очистить всё",
|
||||
@ -393,7 +394,7 @@
|
||||
"im_media": "Медиа",
|
||||
"im_media_photos": "Фотографии",
|
||||
"im_media_video": "Видео",
|
||||
"im_media_documents": "Files",
|
||||
"im_media_documents": "Файлы",
|
||||
"im_media_audio": "Голосовые сообщения",
|
||||
"im_pluralize_participants": "{'one': '{} участник', 'few': '{} участника', 'many': '{} участников', 'other': '{} участников'}",
|
||||
"im_show_recent_messages": "Показать последние сообщения",
|
||||
@ -472,7 +473,9 @@
|
||||
"password_recover_submit": "Отправить",
|
||||
"login_controller_unknown_country": "Неизвестно",
|
||||
"message_forwarded_message": "Пересланное сообщение",
|
||||
"message_via_bot": "via {bot}",
|
||||
"message_forwarded_message_mobile": "Переслано от {from}, {date}",
|
||||
"message_forwarded_via_message_mobile": "Forwarded from {from} via {bot}, {date}",
|
||||
"message_attach_audio_message": "Запись голоса",
|
||||
"message_attach_audio_play": "Воспроизвести",
|
||||
"message_attach_document_open": "Открыть",
|
||||
|
@ -364,7 +364,7 @@ EmojiTooltip.prototype.createTooltip = function () {
|
||||
|
||||
|
||||
EmojiTooltip.prototype.selectCategory = function (cat, force) {
|
||||
if (this.cat === cat && !force) {
|
||||
if (!this.tab && this.cat === cat && !force) {
|
||||
return false;
|
||||
}
|
||||
$('.active', this.categoriesEl).removeClass('active');
|
||||
@ -566,6 +566,12 @@ EmojiTooltip.prototype.onStickersScroll = function (scrollable, scrollTop) {
|
||||
this.activateStickerCategory();
|
||||
};
|
||||
|
||||
EmojiTooltip.prototype.onStickersChanged = function () {
|
||||
if (this.tab) {
|
||||
this.updateStickersContents(true);
|
||||
}
|
||||
};
|
||||
|
||||
EmojiTooltip.prototype.activateStickerCategory = function () {
|
||||
var categoriesEl = this.categoriesEl[1];
|
||||
var categoryEl = categoriesEl.childNodes[this.cat];
|
||||
@ -668,19 +674,77 @@ EmojiPanel.prototype.update = function () {
|
||||
|
||||
|
||||
function MessageComposer (textarea, options) {
|
||||
var self = this;
|
||||
|
||||
this.textareaEl = $(textarea);
|
||||
|
||||
this.setUpInput();
|
||||
|
||||
this.autoCompleteWrapEl = $('<div class="composer_dropdown_wrap"></div>').appendTo(document.body);
|
||||
this.autoCompleteEl = $('<ul class="composer_dropdown dropdown-menu"></ul>').appendTo(this.autoCompleteWrapEl);
|
||||
var autoCompleteEl = $('<div></div>').appendTo(this.autoCompleteWrapEl);
|
||||
|
||||
options.dropdownDirective(autoCompleteEl, function (scope, newAutoCompleteEl) {
|
||||
self.autoCompleteEl = newAutoCompleteEl;
|
||||
self.autoCompleteScope = scope;
|
||||
self.setUpAutoComplete();
|
||||
});
|
||||
|
||||
this.isActive = false;
|
||||
|
||||
this.onTyping = options.onTyping;
|
||||
this.onMessageSubmit = options.onMessageSubmit;
|
||||
this.getSendOnEnter = options.getSendOnEnter;
|
||||
this.onFilePaste = options.onFilePaste;
|
||||
this.onCommandSend = options.onCommandSend;
|
||||
this.onInlineResultSend = options.onInlineResultSend;
|
||||
this.mentions = options.mentions;
|
||||
this.commands = options.commands;
|
||||
}
|
||||
|
||||
MessageComposer.autoCompleteRegEx = /(\s|^)(:|@|\/)([A-Za-z0-9\-\+\*@_]*)$/;
|
||||
|
||||
|
||||
MessageComposer.prototype.setUpInput = function () {
|
||||
this.inlinePlaceholderWrap = $('<div class="im_inline_placeholder_wrap"></div>').prependTo(this.textareaEl[0].parentNode);
|
||||
this.inlinePlaceholderPrefixEl = $('<span class="im_inline_placeholder_prefix"></span>').appendTo(this.inlinePlaceholderWrap);
|
||||
this.inlinePlaceholderEl = $('<span class="im_inline_placeholder"></span>').appendTo(this.inlinePlaceholderWrap);
|
||||
|
||||
if ('contentEditable' in document.body) {
|
||||
this.setUpRich();
|
||||
} else {
|
||||
this.setUpPlaintext();
|
||||
}
|
||||
|
||||
if (!Config.Mobile) {
|
||||
var sbWidth = getScrollWidth();
|
||||
if (sbWidth) {
|
||||
(this.richTextareaEl || this.textareaEl).css({marginRight: -sbWidth});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MessageComposer.prototype.setInlinePlaceholder = function (prefix, placeholder) {
|
||||
this.inlinePlaceholderPrefix = prefix
|
||||
this.inlinePlaceholderPrefixEl.html(encodeEntities(prefix));
|
||||
this.inlinePlaceholderEl.html(encodeEntities(placeholder));
|
||||
this.onChange();
|
||||
}
|
||||
|
||||
MessageComposer.prototype.updateInlinePlaceholder = function () {
|
||||
var prefix = this.inlinePlaceholderPrefix;
|
||||
if (prefix) {
|
||||
var value = this.textareaEl.val();
|
||||
this.inlinePlaceholderWrap.toggleClass('active', value == prefix);
|
||||
}
|
||||
}
|
||||
|
||||
MessageComposer.prototype.setUpAutoComplete = function () {
|
||||
this.scroller = new Scroller(this.autoCompleteEl, {maxHeight: 180});
|
||||
|
||||
var self = this;
|
||||
this.autoCompleteEl.on('mousedown', function (e) {
|
||||
e = e.originalEvent || e;
|
||||
var target = $(e.target), mention, code, command;
|
||||
var target = $(e.target), mention, code, command, inlineID;
|
||||
if (target[0].tagName != 'A') {
|
||||
target = $(target[0].parentNode);
|
||||
}
|
||||
@ -699,37 +763,14 @@ function MessageComposer (textarea, options) {
|
||||
}
|
||||
self.hideSuggestions();
|
||||
}
|
||||
if (inlineID = target.attr('data-inlineid')) {
|
||||
if (self.onInlineResultSend) {
|
||||
self.onInlineResultSend(inlineID);
|
||||
}
|
||||
self.hideSuggestions();
|
||||
}
|
||||
return cancelEvent(e);
|
||||
});
|
||||
|
||||
this.isActive = false;
|
||||
|
||||
this.onTyping = options.onTyping;
|
||||
this.onMessageSubmit = options.onMessageSubmit;
|
||||
this.getSendOnEnter = options.getSendOnEnter;
|
||||
this.onFilePaste = options.onFilePaste;
|
||||
this.mentions = options.mentions;
|
||||
this.commands = options.commands;
|
||||
this.getPeerImage = options.getPeerImage;
|
||||
this.onCommandSend = options.onCommandSend;
|
||||
}
|
||||
|
||||
MessageComposer.autoCompleteRegEx = /(\s|^)(:|@|\/)([A-Za-z0-9\-\+\*@_]*)$/;
|
||||
|
||||
|
||||
MessageComposer.prototype.setUpInput = function () {
|
||||
if ('contentEditable' in document.body) {
|
||||
this.setUpRich();
|
||||
} else {
|
||||
this.setUpPlaintext();
|
||||
}
|
||||
|
||||
if (!Config.Mobile) {
|
||||
var sbWidth = getScrollWidth();
|
||||
if (sbWidth) {
|
||||
(this.richTextareaEl || this.textareaEl).css({marginRight: -sbWidth});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MessageComposer.prototype.setUpRich = function () {
|
||||
@ -763,7 +804,7 @@ MessageComposer.prototype.onKeyEvent = function (e) {
|
||||
if (this.keyupStarted === undefined) {
|
||||
this.keyupStarted = now;
|
||||
}
|
||||
if (now - this.keyupStarted > 10000) {
|
||||
if (now - this.keyupStarted > 3000 || true) {
|
||||
this.onChange();
|
||||
}
|
||||
else {
|
||||
@ -771,6 +812,8 @@ MessageComposer.prototype.onKeyEvent = function (e) {
|
||||
if (this.wasEmpty != !length) {
|
||||
this.wasEmpty = !this.wasEmpty;
|
||||
this.onChange();
|
||||
} else if (this.inlinePlaceholderPrefix) {
|
||||
this.onChange();
|
||||
} else {
|
||||
this.updateValueTO = setTimeout(this.onChange.bind(this), 1000);
|
||||
}
|
||||
@ -797,48 +840,57 @@ MessageComposer.prototype.onKeyEvent = function (e) {
|
||||
if (this.autocompleteShown) {
|
||||
if (e.keyCode == 38 || e.keyCode == 40) { // UP / DOWN
|
||||
var next = e.keyCode == 40;
|
||||
var currentSelected = $(this.autoCompleteEl).find('.composer_autocomplete_option_active');
|
||||
var currentSel = $(this.autoCompleteEl).find('li.composer_autocomplete_option_active');
|
||||
var allLIs = Array.prototype.slice.call($(this.autoCompleteEl).find('li'));
|
||||
var nextSel;
|
||||
|
||||
if (currentSelected.length) {
|
||||
var currentSelectedWrap = currentSelected[0].parentNode;
|
||||
var nextWrap = currentSelectedWrap[next ? 'nextSibling' : 'previousSibling'];
|
||||
currentSelected.removeClass('composer_autocomplete_option_active');
|
||||
if (nextWrap) {
|
||||
$(nextWrap).find('a').addClass('composer_autocomplete_option_active');
|
||||
this.scroller.scrollToNode(nextWrap);
|
||||
if (currentSel.length) {
|
||||
var pos = allLIs.indexOf(currentSel[0]);
|
||||
var nextPos = pos + (next ? 1 : -1);
|
||||
nextSel = allLIs[nextPos];
|
||||
currentSel.removeClass('composer_autocomplete_option_active');
|
||||
if (nextSel) {
|
||||
$(nextSel).addClass('composer_autocomplete_option_active');
|
||||
this.scroller.scrollToNode(nextSel);
|
||||
return cancelEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
var childNodes = this.autoCompleteEl[0].childNodes;
|
||||
var nextWrap = childNodes[next ? 0 : childNodes.length - 1];
|
||||
this.scroller.scrollToNode(nextWrap);
|
||||
$(nextWrap).find('a').addClass('composer_autocomplete_option_active');
|
||||
nextSel = allLIs[next ? 0 : allLIs.length - 1];
|
||||
this.scroller.scrollToNode(nextSel);
|
||||
$(nextSel).addClass('composer_autocomplete_option_active');
|
||||
|
||||
return cancelEvent(e);
|
||||
}
|
||||
|
||||
if (e.keyCode == 13 || e.keyCode == 9) { // Enter or Tab
|
||||
var currentSelected = $(this.autoCompleteEl).find('.composer_autocomplete_option_active');
|
||||
if (!currentSelected.length && e.keyCode == 9) {
|
||||
currentSelected = $(this.autoCompleteEl[0].childNodes[0]).find('a');
|
||||
var currentSel = $(this.autoCompleteEl).find('li.composer_autocomplete_option_active');
|
||||
if (!currentSel.length && e.keyCode == 9) {
|
||||
currentSel = $(this.autoCompleteEl).find('li:first');
|
||||
}
|
||||
var code, mention, command;
|
||||
if (code = currentSelected.attr('data-code')) {
|
||||
currentSel = currentSel.find('a:first');
|
||||
var code, mention, command, inlineID;
|
||||
if (code = currentSel.attr('data-code')) {
|
||||
this.onEmojiSelected(code, true);
|
||||
EmojiHelper.pushPopularEmoji(code);
|
||||
return cancelEvent(e);
|
||||
}
|
||||
if (mention = currentSelected.attr('data-mention')) {
|
||||
if (mention = currentSel.attr('data-mention')) {
|
||||
this.onMentionSelected(mention);
|
||||
return cancelEvent(e);
|
||||
}
|
||||
if (command = currentSelected.attr('data-command')) {
|
||||
if (command = currentSel.attr('data-command')) {
|
||||
if (this.onCommandSelected) {
|
||||
this.onCommandSelected(command, e.keyCode == 9);
|
||||
}
|
||||
return cancelEvent(e);
|
||||
}
|
||||
if (inlineID = currentSel.attr('data-inlineid')) {
|
||||
if (self.onInlineResultSend) {
|
||||
self.onInlineResultSend(inlineID);
|
||||
}
|
||||
return cancelEvent(e);
|
||||
}
|
||||
checkSubmit = true;
|
||||
}
|
||||
}
|
||||
@ -918,6 +970,13 @@ MessageComposer.prototype.checkAutocomplete = function (forceFull) {
|
||||
var value = textarea.value;
|
||||
}
|
||||
|
||||
if (value &&
|
||||
this.curInlineResults &&
|
||||
this.curInlineResults.text == value) {
|
||||
this.showInlineSuggestions(this.curInlineResults);
|
||||
return;
|
||||
};
|
||||
|
||||
if (!forceFull) {
|
||||
value = value.substr(0, pos);
|
||||
}
|
||||
@ -1268,6 +1327,7 @@ MessageComposer.prototype.onChange = function (e) {
|
||||
delete this.keyupStarted;
|
||||
this.textareaEl.val(getRichValue(this.richTextareaEl[0])).trigger('change');
|
||||
}
|
||||
this.updateInlinePlaceholder();
|
||||
}
|
||||
|
||||
MessageComposer.prototype.getEmojiHtml = function (code, emoji) {
|
||||
@ -1347,8 +1407,7 @@ MessageComposer.prototype.blur = function () {
|
||||
}
|
||||
}
|
||||
|
||||
MessageComposer.prototype.renderSuggestions = function (html) {
|
||||
this.autoCompleteEl.html(html.join(''));
|
||||
MessageComposer.prototype.renderSuggestions = function () {
|
||||
this.autoCompleteWrapEl.show();
|
||||
this.scroller.reinit();
|
||||
this.updatePosition();
|
||||
@ -1356,75 +1415,66 @@ MessageComposer.prototype.renderSuggestions = function (html) {
|
||||
}
|
||||
|
||||
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-w', iconSize, ' emoji-spritesheet-' + categoryIndex + '" style="background-position: -' + x + 'px -' + y + 'px;"></i><span class="composer_emoji_shortcut">:' + encodeEntities(emoticonData[1][0]) + ':</span></a></li>');
|
||||
}
|
||||
}
|
||||
|
||||
this.renderSuggestions(html);
|
||||
var self = this;
|
||||
setZeroTimeout(function () {
|
||||
self.autoCompleteScope.$apply(function () {
|
||||
self.autoCompleteScope.type = 'emoji';
|
||||
self.autoCompleteScope.emojiCodes = codes;
|
||||
});
|
||||
onContentLoaded(function () {
|
||||
self.renderSuggestions();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
MessageComposer.prototype.showMentionSuggestions = function (users) {
|
||||
var html = [];
|
||||
var user;
|
||||
var count = users.length;
|
||||
var i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
user = users[i];
|
||||
html.push('<li><a class="composer_mention_option" data-mention="' + user.username + '"><span class="composer_user_photo" data-user-id="' + user.id + '"></span><span class="composer_user_name">' + user.rFullName + '</span><span class="composer_user_mention">@' + user.username + '</span></a></li>');
|
||||
}
|
||||
|
||||
this.renderSuggestions(html);
|
||||
var self = this;
|
||||
this.autoCompleteEl.find('.composer_user_photo').each(function (k, element) {
|
||||
self.getPeerImage($(element), element.getAttribute('data-user-id'));
|
||||
setZeroTimeout(function () {
|
||||
self.autoCompleteScope.$apply(function () {
|
||||
self.autoCompleteScope.type = 'mentions';
|
||||
self.autoCompleteScope.mentionUsers = users;
|
||||
});
|
||||
onContentLoaded(function () {
|
||||
self.renderSuggestions();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
MessageComposer.prototype.showCommandsSuggestions = function (commands) {
|
||||
var html = [];
|
||||
var command;
|
||||
var count = Math.min(200, commands.length);
|
||||
var i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
command = commands[i];
|
||||
html.push('<li><a class="composer_command_option" data-command="' + encodeEntities(command.value) + '"><span class="composer_user_photo" data-user-id="' + command.botID + '"></span><span class="composer_command_value">' + encodeEntities(command.value) + '</span><span class="composer_command_desc">' + command.rDescription + '</span></a></li>');
|
||||
}
|
||||
|
||||
this.renderSuggestions(html);
|
||||
|
||||
var self = this;
|
||||
var usedImages = {};
|
||||
this.autoCompleteEl.find('.composer_user_photo').each(function (k, element) {
|
||||
var noReplace = true;
|
||||
var botID = element.getAttribute('data-user-id');
|
||||
if (!usedImages[botID]) {
|
||||
usedImages[botID] = true;
|
||||
noReplace = false;
|
||||
}
|
||||
self.getPeerImage($(element), botID, noReplace);
|
||||
setZeroTimeout(function () {
|
||||
self.autoCompleteScope.$apply(function () {
|
||||
self.autoCompleteScope.type = 'commands';
|
||||
self.autoCompleteScope.commands = commands;
|
||||
});
|
||||
onContentLoaded(function () {
|
||||
self.renderSuggestions();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
MessageComposer.prototype.showInlineSuggestions = function (botResults) {
|
||||
if (!botResults || !botResults.results.length) {
|
||||
this.hideSuggestions();
|
||||
return;
|
||||
}
|
||||
var self = this;
|
||||
setZeroTimeout(function () {
|
||||
self.autoCompleteScope.$apply(function () {
|
||||
self.autoCompleteScope.type = 'inline';
|
||||
self.autoCompleteScope.botResults = botResults;
|
||||
});
|
||||
onContentLoaded(function () {
|
||||
self.renderSuggestions();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
MessageComposer.prototype.setInlineSuggestions = function (botResults) {
|
||||
this.curInlineResults = botResults;
|
||||
this.checkAutocomplete();
|
||||
}
|
||||
|
||||
MessageComposer.prototype.updatePosition = function () {
|
||||
var offset = (this.richTextareaEl || this.textareaEl).offset();
|
||||
var height = this.scroller.updateHeight();
|
||||
@ -1438,6 +1488,8 @@ MessageComposer.prototype.updatePosition = function () {
|
||||
}
|
||||
|
||||
MessageComposer.prototype.hideSuggestions = function () {
|
||||
// console.trace();
|
||||
// return;
|
||||
this.autoCompleteWrapEl.hide();
|
||||
delete this.autocompleteShown;
|
||||
}
|
||||
|
@ -181,7 +181,10 @@ angular.module('myApp.services')
|
||||
}
|
||||
|
||||
NotificationsManager.savePeerSettings(peerID, dialog.notify_settings);
|
||||
ApiUpdatesManager.addChannelState(channelID, dialog.pts);
|
||||
|
||||
if (dialog.pts) {
|
||||
ApiUpdatesManager.addChannelState(channelID, dialog.pts);
|
||||
}
|
||||
}
|
||||
|
||||
function getTopMessages (limit) {
|
||||
@ -1291,10 +1294,12 @@ angular.module('myApp.services')
|
||||
isChannel = AppPeersManager.isChannel(peerID),
|
||||
isMegagroup = isChannel && AppPeersManager.isMegagroup(peerID),
|
||||
asChannel = isChannel && !isMegagroup ? true : false,
|
||||
entities = [],
|
||||
entities = options.entities || [],
|
||||
message;
|
||||
|
||||
text = RichTextProcessor.parseMarkdown(text, entities);
|
||||
if (!options.viaBotID) {
|
||||
text = RichTextProcessor.parseMarkdown(text, entities);
|
||||
}
|
||||
|
||||
if (historyStorage === undefined) {
|
||||
historyStorage = historiesStorage[peerID] = {count: null, history: [], pending: []};
|
||||
@ -1328,6 +1333,7 @@ angular.module('myApp.services')
|
||||
message: text,
|
||||
random_id: randomIDS,
|
||||
reply_to_msg_id: replyToMsgID,
|
||||
via_bot_id: options.viaBotID,
|
||||
entities: entities,
|
||||
views: asChannel && 1,
|
||||
pending: true
|
||||
@ -1359,21 +1365,34 @@ angular.module('myApp.services')
|
||||
if (replyToMsgID) {
|
||||
flags |= 1;
|
||||
}
|
||||
if (entities.length) {
|
||||
flags |= 8;
|
||||
}
|
||||
if (asChannel) {
|
||||
flags |= 16;
|
||||
}
|
||||
var apiPromise;
|
||||
if (options.viaBotID) {
|
||||
apiPromise = MtpApiManager.invokeApi('messages.sendInlineBotResult', {
|
||||
flags: flags,
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
random_id: randomID,
|
||||
reply_to_msg_id: getMessageLocalID(replyToMsgID),
|
||||
query_id: options.queryID,
|
||||
id: options.resultID
|
||||
}, sentRequestOptions);
|
||||
} else {
|
||||
if (entities.length) {
|
||||
flags |= 8;
|
||||
}
|
||||
apiPromise = MtpApiManager.invokeApi('messages.sendMessage', {
|
||||
flags: flags,
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
message: text,
|
||||
random_id: randomID,
|
||||
reply_to_msg_id: getMessageLocalID(replyToMsgID),
|
||||
entities: entities
|
||||
}, sentRequestOptions)
|
||||
}
|
||||
// console.log(flags, entities);
|
||||
MtpApiManager.invokeApi('messages.sendMessage', {
|
||||
flags: flags,
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
message: text,
|
||||
random_id: randomID,
|
||||
reply_to_msg_id: getMessageLocalID(replyToMsgID),
|
||||
entities: entities
|
||||
}, sentRequestOptions).then(function (updates) {
|
||||
apiPromise.then(function (updates) {
|
||||
if (updates._ == 'updateShortSentMessage') {
|
||||
message.flags = updates.flags;
|
||||
message.date = updates.date;
|
||||
@ -1637,7 +1656,8 @@ angular.module('myApp.services')
|
||||
case 'inputMediaPhoto':
|
||||
media = {
|
||||
_: 'messageMediaPhoto',
|
||||
photo: AppPhotosManager.getPhoto(inputMedia.id.id)
|
||||
photo: AppPhotosManager.getPhoto(inputMedia.id.id),
|
||||
caption: inputMedia.caption || ''
|
||||
};
|
||||
break;
|
||||
|
||||
@ -1648,9 +1668,14 @@ angular.module('myApp.services')
|
||||
};
|
||||
media = {
|
||||
_: 'messageMediaDocument',
|
||||
'document': doc
|
||||
'document': doc,
|
||||
caption: inputMedia.caption || ''
|
||||
};
|
||||
break;
|
||||
|
||||
case 'messageMediaPending':
|
||||
media = inputMedia;
|
||||
break;
|
||||
}
|
||||
|
||||
var flags = 0;
|
||||
@ -1684,6 +1709,7 @@ angular.module('myApp.services')
|
||||
media: media,
|
||||
random_id: randomIDS,
|
||||
reply_to_msg_id: replyToMsgID,
|
||||
via_bot_id: options.viaBotID,
|
||||
views: asChannel && 1,
|
||||
pending: true
|
||||
};
|
||||
@ -1718,13 +1744,26 @@ angular.module('myApp.services')
|
||||
sentRequestOptions.afterMessageID = pendingAfterMsgs[peerID].messageID;
|
||||
}
|
||||
|
||||
MtpApiManager.invokeApi('messages.sendMedia', {
|
||||
flags: flags,
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
media: inputMedia,
|
||||
random_id: randomID,
|
||||
reply_to_msg_id: getMessageLocalID(replyToMsgID)
|
||||
}, sentRequestOptions).then(function (updates) {
|
||||
var apiPromise;
|
||||
if (options.viaBotID) {
|
||||
apiPromise = MtpApiManager.invokeApi('messages.sendInlineBotResult', {
|
||||
flags: flags,
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
random_id: randomID,
|
||||
reply_to_msg_id: getMessageLocalID(replyToMsgID),
|
||||
query_id: options.queryID,
|
||||
id: options.resultID
|
||||
}, sentRequestOptions);
|
||||
} else {
|
||||
apiPromise = MtpApiManager.invokeApi('messages.sendMedia', {
|
||||
flags: flags,
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
media: inputMedia,
|
||||
random_id: randomID,
|
||||
reply_to_msg_id: getMessageLocalID(replyToMsgID)
|
||||
}, sentRequestOptions);
|
||||
}
|
||||
apiPromise.then(function (updates) {
|
||||
ApiUpdatesManager.processUpdateMessage(updates);
|
||||
}, function (error) {
|
||||
toggleError(true);
|
||||
@ -3007,7 +3046,7 @@ angular.module('myApp.services')
|
||||
};
|
||||
}
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
return {
|
||||
getConversations: getConversations,
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
|
||||
.service('AppUsersManager', function ($rootScope, $modal, $modalStack, $filter, $q, qSync, MtpApiFileManager, MtpApiManager, RichTextProcessor, ErrorService, Storage, _) {
|
||||
.service('AppUsersManager', function ($rootScope, $modal, $modalStack, $filter, $q, qSync, MtpApiManager, RichTextProcessor, ErrorService, Storage, _) {
|
||||
var users = {},
|
||||
usernames = {},
|
||||
userAccess = {},
|
||||
@ -575,7 +575,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
|
||||
})
|
||||
|
||||
.service('AppChatsManager', function ($q, $rootScope, $modal, _, MtpApiFileManager, MtpApiManager, AppUsersManager, AppPhotosManager, RichTextProcessor) {
|
||||
.service('AppChatsManager', function ($q, $rootScope, $modal, _, MtpApiManager, AppUsersManager, AppPhotosManager, RichTextProcessor) {
|
||||
var chats = {},
|
||||
usernames = {},
|
||||
channelAccess = {},
|
||||
@ -833,7 +833,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
}
|
||||
})
|
||||
|
||||
.service('AppPeersManager', function (qSync, AppUsersManager, AppChatsManager, MtpApiManager) {
|
||||
.service('AppPeersManager', function ($q, qSync, AppUsersManager, AppChatsManager, MtpApiManager) {
|
||||
|
||||
function getInputPeer (peerString) {
|
||||
var firstChar = peerString.charAt(0),
|
||||
@ -944,6 +944,24 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
});
|
||||
}
|
||||
|
||||
function resolveInlineMention (username) {
|
||||
return resolveUsername(username).then(function (peerID) {
|
||||
if (peerID > 0) {
|
||||
var bot = AppUsersManager.getUser(peerID);
|
||||
if (bot.pFlags.bot && bot.bot_inline_placeholder !== undefined) {
|
||||
return qSync.when({
|
||||
id: peerID,
|
||||
placeholder: bot.bot_inline_placeholder
|
||||
});
|
||||
}
|
||||
}
|
||||
return $q.reject();
|
||||
}, function (error) {
|
||||
error.handled = true;
|
||||
return $q.reject(error);
|
||||
});
|
||||
}
|
||||
|
||||
function getPeerID (peerString) {
|
||||
if (angular.isObject(peerString)) {
|
||||
return peerString.user_id
|
||||
@ -990,6 +1008,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
getPeer: getPeer,
|
||||
getPeerPhoto: getPeerPhoto,
|
||||
resolveUsername: resolveUsername,
|
||||
resolveInlineMention: resolveInlineMention,
|
||||
isChannel: isChannel,
|
||||
isMegagroup: isMegagroup,
|
||||
isBot: isBot
|
||||
@ -1222,6 +1241,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
});
|
||||
break;
|
||||
}
|
||||
return $q.reject(error);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1907,7 +1927,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
}
|
||||
})
|
||||
|
||||
.service('AppDocsManager', function ($sce, $rootScope, $modal, $window, $q, RichTextProcessor, MtpApiFileManager, FileManager, qSync) {
|
||||
.service('AppDocsManager', function ($sce, $rootScope, $modal, $window, $q, $timeout, RichTextProcessor, MtpApiFileManager, FileManager, qSync) {
|
||||
var docs = {},
|
||||
docsForHistory = {},
|
||||
windowW = $(window).width(),
|
||||
@ -2096,13 +2116,18 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
});
|
||||
|
||||
downloadPromise.then(function (blob) {
|
||||
delete historyDoc.progress;
|
||||
if (blob) {
|
||||
FileManager.getFileCorrectUrl(blob, doc.mime_type).then(function (url) {
|
||||
historyDoc.url = $sce.trustAsResourceUrl(url);
|
||||
var trustedUrl = $sce.trustAsResourceUrl(url);
|
||||
historyDoc.url = trustedUrl;
|
||||
doc.url = trustedUrl;
|
||||
})
|
||||
historyDoc.downloaded = true;
|
||||
}
|
||||
historyDoc.progress.percent = 100;
|
||||
$timeout(function () {
|
||||
delete historyDoc.progress;
|
||||
});
|
||||
console.log('file save done');
|
||||
}, function (e) {
|
||||
console.log('document download failed', e);
|
||||
@ -2274,24 +2299,81 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
}
|
||||
})
|
||||
|
||||
.service('AppStickersManager', function ($q, $rootScope, $modal, _, FileManager, MtpApiManager, MtpApiFileManager, AppDocsManager, Storage) {
|
||||
.service('AppStickersManager', function ($q, $rootScope, $modal, _, FileManager, MtpApiManager, AppDocsManager, Storage, ApiUpdatesManager) {
|
||||
|
||||
var currentStickers = [];
|
||||
var currentStickersets = [];
|
||||
var installedStickersets = {};
|
||||
var stickersetItems = {};
|
||||
var applied = false;
|
||||
var started = false;
|
||||
var applied = false;
|
||||
var currentStickerSets = [];
|
||||
|
||||
$rootScope.$on('apiUpdate', function (e, update) {
|
||||
if (update._ != 'updateStickerSets' &&
|
||||
update._ != 'updateNewStickerSet' &&
|
||||
update._ != 'updateDelStickerSet' &&
|
||||
update._ != 'updateStickerSetsOrder') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Storage.get('all_stickers').then(function (stickers) {
|
||||
if (!stickers ||
|
||||
stickers.layer != Config.Schema.API.layer) {
|
||||
$rootScope.$broadcast('stickers_changed');
|
||||
}
|
||||
switch (update._) {
|
||||
case 'updateNewStickerSet':
|
||||
var fullSet = update.stickerset;
|
||||
var set = fullSet.set;
|
||||
var pos = false;
|
||||
for (var i = 0, len = stickers.sets.length; i < len; i++) {
|
||||
if (stickers.sets[i].id == set.id) {
|
||||
pos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pos !== false) {
|
||||
stickers.sets.splice(pos, 1);
|
||||
}
|
||||
set.pFlags.installed = true;
|
||||
stickers.sets.unshift(set);
|
||||
stickers.fullSets[set.id] = fullSet;
|
||||
break;
|
||||
|
||||
case 'updateDelStickerSet':
|
||||
var set;
|
||||
for (var i = 0, len = stickers.sets.length; i < len; i++) {
|
||||
set = stickers.sets[i];
|
||||
if (set.id == update.id) {
|
||||
set.pFlags.installed = false;
|
||||
stickers.sets.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete stickers.fullSets[update.id];
|
||||
break;
|
||||
|
||||
case 'updateStickerSetsOrder':
|
||||
var order = update.order;
|
||||
stickers.sets.sort(function (a, b) {
|
||||
return order.indexOf(a.id) - order.indexOf(b.id);
|
||||
});
|
||||
break;
|
||||
}
|
||||
stickers.hash = getStickerSetsHash(stickers.sets);
|
||||
stickers.date = 0;
|
||||
Storage.set({all_stickers: stickers}).then(function () {
|
||||
$rootScope.$broadcast('stickers_changed');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
return {
|
||||
start: start,
|
||||
getStickers: getStickers,
|
||||
openStickersetLink: openStickersetLink,
|
||||
openStickerset: openStickerset,
|
||||
installStickerset: installStickerset,
|
||||
pushPopularSticker: pushPopularSticker,
|
||||
getStickers: getStickers,
|
||||
getStickerset: getStickerset,
|
||||
getStickersImages: getStickersImages
|
||||
getStickerset: getStickerset
|
||||
};
|
||||
|
||||
function start () {
|
||||
@ -2301,6 +2383,109 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
}
|
||||
}
|
||||
|
||||
function getStickers (force) {
|
||||
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) && !force) {
|
||||
return processRawStickers(stickers);
|
||||
}
|
||||
return MtpApiManager.invokeApi('messages.getAllStickers', {
|
||||
hash: stickers && stickers.hash || ''
|
||||
}).then(function (newStickers) {
|
||||
var notModified = newStickers._ == 'messages.allStickersNotModified';
|
||||
if (notModified) {
|
||||
newStickers = stickers;
|
||||
}
|
||||
newStickers.date = tsNow(true) + 3600;
|
||||
newStickers.layer = layer;
|
||||
delete newStickers._;
|
||||
|
||||
if (notModified) {
|
||||
Storage.set({all_stickers: newStickers});
|
||||
return processRawStickers(newStickers);
|
||||
}
|
||||
|
||||
return getStickerSets(newStickers, stickers && stickers.fullSets).then(function () {
|
||||
Storage.set({all_stickers: newStickers});
|
||||
return processRawStickers(newStickers);
|
||||
});
|
||||
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
function processRawStickers(stickers) {
|
||||
if (applied !== stickers.hash) {
|
||||
applied = stickers.hash;
|
||||
var i, j, len1, len2, doc, set, docIDs, documents;
|
||||
|
||||
currentStickerSets = [];
|
||||
len1 = stickers.sets.length;
|
||||
for (i = 0; i < len1; i++) {
|
||||
set = stickers.sets[i];
|
||||
if (set.pFlags.disabled) {
|
||||
continue;
|
||||
}
|
||||
documents = stickers.fullSets[set.id].documents;
|
||||
len2 = documents.length;
|
||||
docIDs = [];
|
||||
for (j = 0; j < len2; j++) {
|
||||
doc = documents[j];
|
||||
AppDocsManager.saveDoc(doc);
|
||||
docIDs.push(doc.id);
|
||||
}
|
||||
set.docIDs = docIDs;
|
||||
currentStickerSets.push(set);
|
||||
}
|
||||
}
|
||||
|
||||
return getPopularStickers().then(function (popularStickers) {
|
||||
var resultStickersets = currentStickerSets;
|
||||
if (popularStickers.length) {
|
||||
resultStickersets = currentStickerSets.slice();
|
||||
var docIDs = [];
|
||||
var i, len;
|
||||
for (i = 0, len = popularStickers.length; i < len; i++) {
|
||||
docIDs.push(popularStickers[i].id);
|
||||
}
|
||||
resultStickersets.unshift({
|
||||
id: 0,
|
||||
title: _('im_stickers_tab_recent_raw'),
|
||||
short_name: '',
|
||||
docIDs: docIDs
|
||||
});
|
||||
}
|
||||
return resultStickersets;
|
||||
});
|
||||
}
|
||||
|
||||
function getStickerSets (allStickers, prevCachedSets) {
|
||||
var promises = [];
|
||||
var cachedSets = prevCachedSets || allStickers.fullSets || {};
|
||||
allStickers.fullSets = {};
|
||||
angular.forEach(allStickers.sets, function (shortSet) {
|
||||
var fullSet = cachedSets[shortSet.id];
|
||||
if (fullSet && fullSet.set.hash == shortSet.hash) {
|
||||
allStickers.fullSets[shortSet.id] = fullSet;
|
||||
} else {
|
||||
var promise = MtpApiManager.invokeApi('messages.getStickerSet', {
|
||||
stickerset: {
|
||||
_: 'inputStickerSetID',
|
||||
id: shortSet.id,
|
||||
access_hash: shortSet.access_hash
|
||||
}
|
||||
}).then(function (fullSet) {
|
||||
allStickers.fullSets[shortSet.id] = fullSet;
|
||||
});
|
||||
promises.push(promise);
|
||||
}
|
||||
});
|
||||
return $q.all(promises);
|
||||
}
|
||||
|
||||
function getPopularStickers () {
|
||||
return Storage.get('stickers_popular').then(function (popStickers) {
|
||||
var result = [];
|
||||
@ -2343,140 +2528,6 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
});
|
||||
}
|
||||
|
||||
function processRawStickers(stickers) {
|
||||
if (applied !== stickers.hash) {
|
||||
applied = stickers.hash;
|
||||
var i, j, len1, len2, doc, set, setItems, fullSet;
|
||||
|
||||
currentStickersets = [];
|
||||
currentStickers = [];
|
||||
len1 = stickers.sets.length;
|
||||
for (i = 0; i < len1; i++) {
|
||||
set = stickers.sets[i];
|
||||
fullSet = stickers.fullSets[set.id];
|
||||
len2 = fullSet.documents.length;
|
||||
setItems = [];
|
||||
for (j = 0; j < len2; j++) {
|
||||
doc = fullSet.documents[j];
|
||||
AppDocsManager.saveDoc(doc);
|
||||
currentStickers.push(doc.id);
|
||||
setItems.push(doc.id);
|
||||
}
|
||||
currentStickersets.push({
|
||||
id: set.id,
|
||||
title: set.title,
|
||||
short_name: set.short_name,
|
||||
installed: (set.flags & (1 << 0)) > 0,
|
||||
disabled: (set.flags & (1 << 1)) > 0,
|
||||
official: (set.flags & (1 << 2)) > 0,
|
||||
docIDs: setItems
|
||||
});
|
||||
installedStickersets[set.id] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return getPopularStickers().then(function (popularStickers) {
|
||||
var resultStickersets = currentStickersets;
|
||||
if (popularStickers.length) {
|
||||
resultStickersets = currentStickersets.slice();
|
||||
var setItems = [];
|
||||
var i, len;
|
||||
for (i = 0, len = popularStickers.length; i < len; i++) {
|
||||
setItems.push(popularStickers[i].id);
|
||||
}
|
||||
resultStickersets.unshift({
|
||||
id: 0,
|
||||
title: _('im_stickers_tab_recent_raw'),
|
||||
short_name: '',
|
||||
installed: true,
|
||||
disabled: false,
|
||||
official: false,
|
||||
docIDs: setItems
|
||||
})
|
||||
}
|
||||
|
||||
return resultStickersets;
|
||||
});
|
||||
}
|
||||
|
||||
function getStickers (force) {
|
||||
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) && !force) {
|
||||
return processRawStickers(stickers);
|
||||
}
|
||||
return MtpApiManager.invokeApi('messages.getAllStickers', {
|
||||
hash: stickers && stickers.hash || ''
|
||||
}).then(function (newStickers) {
|
||||
var notModified = newStickers._ == 'messages.allStickersNotModified';
|
||||
if (notModified) {
|
||||
newStickers = stickers;
|
||||
}
|
||||
newStickers.date = tsNow(true) + 3600;
|
||||
newStickers.layer = layer;
|
||||
delete newStickers._;
|
||||
|
||||
if (notModified) {
|
||||
Storage.set({all_stickers: newStickers});
|
||||
return processRawStickers(newStickers);
|
||||
}
|
||||
|
||||
return getStickerSets(newStickers).then(function () {
|
||||
Storage.set({all_stickers: newStickers});
|
||||
return processRawStickers(newStickers);
|
||||
});
|
||||
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
function getStickerSets (allStickers) {
|
||||
var promises = [];
|
||||
var cachedSets = allStickers.fullSets || {};
|
||||
allStickers.fullSets = {};
|
||||
angular.forEach(allStickers.sets, function (shortSet) {
|
||||
var fullSet = cachedSets[shortSet.id];
|
||||
if (fullSet && fullSet.set.hash == shortSet.hash) {
|
||||
allStickers.fullSets[shortSet.id] = fullSet;
|
||||
} else {
|
||||
var promise = MtpApiManager.invokeApi('messages.getStickerSet', {
|
||||
stickerset: {
|
||||
_: 'inputStickerSetID',
|
||||
id: shortSet.id,
|
||||
access_hash: shortSet.access_hash
|
||||
}
|
||||
}).then(function (fullSet) {
|
||||
allStickers.fullSets[shortSet.id] = fullSet;
|
||||
});
|
||||
promises.push(promise);
|
||||
}
|
||||
});
|
||||
return $q.all(promises);
|
||||
}
|
||||
|
||||
function downloadStickerThumb (docID) {
|
||||
var doc = AppDocsManager.getDoc(docID);
|
||||
var thumbLocation = angular.copy(doc.thumb.location);
|
||||
thumbLocation.sticker = true;
|
||||
return MtpApiFileManager.downloadSmallFile(thumbLocation).then(function (blob) {
|
||||
return {
|
||||
id: doc.id,
|
||||
src: FileManager.getUrl(blob, 'image/webp')
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function getStickersImages () {
|
||||
var promises = [];
|
||||
angular.forEach(currentStickers, function (docID) {
|
||||
promises.push(downloadStickerThumb (docID));
|
||||
});
|
||||
return $q.all(promises);
|
||||
}
|
||||
|
||||
function getStickerset (inputStickerset) {
|
||||
return MtpApiManager.invokeApi('messages.getStickerSet', {
|
||||
stickerset: inputStickerset
|
||||
@ -2484,31 +2535,32 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
for (var i = 0; i < result.documents.length; i++) {
|
||||
AppDocsManager.saveDoc(result.documents[i]);
|
||||
}
|
||||
result.installed = installedStickersets[result.set.id] !== undefined;
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
function installStickerset (set, uninstall) {
|
||||
function installStickerset (fullSet, uninstall) {
|
||||
var method = uninstall
|
||||
? 'messages.uninstallStickerSet'
|
||||
: 'messages.installStickerSet';
|
||||
var inputStickerset = {
|
||||
_: 'inputStickerSetID',
|
||||
id: set.id,
|
||||
access_hash: set.access_hash
|
||||
id: fullSet.set.id,
|
||||
access_hash: fullSet.set.access_hash
|
||||
};
|
||||
return MtpApiManager.invokeApi(method, {
|
||||
stickerset: inputStickerset,
|
||||
disabled: false
|
||||
}).then(function (result) {
|
||||
var update;
|
||||
if (uninstall) {
|
||||
delete installedStickersets[set.id];
|
||||
update = {_: 'updateDelStickerSet', id: fullSet.set.id};
|
||||
} else {
|
||||
installedStickersets[set.id] = true;
|
||||
update = {_: 'updateNewStickerSet', stickerset: fullSet};
|
||||
}
|
||||
Storage.remove('all_stickers').then(function () {
|
||||
getStickers(true);
|
||||
ApiUpdatesManager.processUpdateMessage({
|
||||
_: 'updateShort',
|
||||
update: update
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -2530,6 +2582,186 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
windowClass: 'stickerset_modal_window mobile_modal'
|
||||
});
|
||||
}
|
||||
|
||||
function getStickerSetsHash (stickerSets) {
|
||||
var acc = 0, set;
|
||||
for (var i = 0; i < stickerSets.length; i++) {
|
||||
set = stickerSets[i];
|
||||
if (set.pFlags.disabled || !set.pFlags.installed) {
|
||||
continue;
|
||||
}
|
||||
acc = ((acc * 20261) + 0x80000000 + set.hash) % 0x80000000;
|
||||
}
|
||||
return acc;
|
||||
}
|
||||
})
|
||||
|
||||
.service('AppInlineBotsManager', function (MtpApiManager, AppMessagesManager, AppDocsManager, AppPhotosManager, RichTextProcessor, AppUsersManager) {
|
||||
|
||||
var inlineResults = {};
|
||||
|
||||
return {
|
||||
sendInlineResult: sendInlineResult,
|
||||
regroupWrappedResults: regroupWrappedResults,
|
||||
getInlineResults: getInlineResults
|
||||
};
|
||||
|
||||
function getInlineResults (botID, query, offset) {
|
||||
return MtpApiManager.invokeApi('messages.getInlineBotResults', {
|
||||
bot: AppUsersManager.getUserInput(botID),
|
||||
query: query,
|
||||
offset: offset
|
||||
}, {timeout: 1, stopTime: -1, noErrorBox: true}).then(function(botResults) {
|
||||
var queryID = botResults.query_id;
|
||||
delete botResults._;
|
||||
delete botResults.flags;
|
||||
delete botResults.query_id;
|
||||
|
||||
angular.forEach(botResults.results, function (result) {
|
||||
var qID = queryID + '_' + result.id;
|
||||
result.qID = qID;
|
||||
result.botID = botID;
|
||||
|
||||
result.rTitle = RichTextProcessor.wrapRichText(result.title, {noLinebreaks: true, noLinks: true});
|
||||
result.rDescription = RichTextProcessor.wrapRichText(result.description, {noLinebreaks: true, noLinks: true});
|
||||
result.initials = (result.url || result.title || result.type || '').substr(0, 1)
|
||||
|
||||
if (result.document) {
|
||||
AppDocsManager.saveDoc(result.document);
|
||||
}
|
||||
if (result.photo) {
|
||||
AppPhotosManager.savePhoto(result.photo);
|
||||
}
|
||||
|
||||
inlineResults[qID] = result;
|
||||
});
|
||||
return botResults;
|
||||
});
|
||||
}
|
||||
|
||||
function regroupWrappedResults (results, rowW, rowH) {
|
||||
if (!results ||
|
||||
!results[0] ||
|
||||
results[0].type != 'photo' && results[0].type != 'gif') {
|
||||
return;
|
||||
}
|
||||
var ratios = [];
|
||||
angular.forEach(results, function (result) {
|
||||
var w, h;
|
||||
if (result._ == 'botInlineMediaResultDocument') {
|
||||
w = result.document.w;
|
||||
h = result.document.h;
|
||||
}
|
||||
else if (result._ == 'botInlineMediaResultPhoto') {
|
||||
var photoSize = (result.photo.sizes || [])[0];
|
||||
w = photoSize && photoSize.w;
|
||||
h = photoSize && photoSize.h;
|
||||
}
|
||||
else {
|
||||
w = result.w;
|
||||
h = result.h;
|
||||
}
|
||||
if (!w || !h) {
|
||||
w = h = 1;
|
||||
}
|
||||
ratios.push(w / h);
|
||||
});
|
||||
|
||||
var rows = [];
|
||||
var curCnt = 0;
|
||||
var curW = 0;
|
||||
angular.forEach(ratios, function (ratio) {
|
||||
var w = ratio * rowH;
|
||||
curW += w;
|
||||
if (!curCnt || curCnt < 4 && curW < (rowW * 1.1)) {
|
||||
curCnt++;
|
||||
} else {
|
||||
rows.push(curCnt);
|
||||
curCnt = 1;
|
||||
curW = w;
|
||||
}
|
||||
});
|
||||
if (curCnt) {
|
||||
rows.push(curCnt);
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
var thumbs = [];
|
||||
var lastRowI = rows.length - 1;
|
||||
angular.forEach(rows, function (rowCnt, rowI) {
|
||||
var lastRow = rowI == lastRowI;
|
||||
var curRatios = ratios.slice(i, i + rowCnt);
|
||||
var sumRatios = 0;
|
||||
angular.forEach(curRatios, function (ratio) {
|
||||
sumRatios += ratio;
|
||||
});
|
||||
angular.forEach(curRatios, function (ratio, j) {
|
||||
var thumbH = rowH;
|
||||
var thumbW = rowW * ratio / sumRatios;
|
||||
var realW = thumbH * ratio;
|
||||
if (lastRow && thumbW > realW) {
|
||||
thumbW = realW;
|
||||
}
|
||||
var result = results[i + j];
|
||||
result.thumbW = Math.floor(thumbW);
|
||||
result.thumbH = Math.floor(thumbH);
|
||||
});
|
||||
|
||||
i += rowCnt;
|
||||
});
|
||||
}
|
||||
|
||||
function sendInlineResult (peerID, qID, options) {
|
||||
var inlineResult = inlineResults[qID];
|
||||
if (inlineResult === undefined) {
|
||||
return false;
|
||||
}
|
||||
var splitted = qID.split('_');
|
||||
var queryID = splitted.shift();
|
||||
var resultID = splitted.join('_');
|
||||
options = options || {};
|
||||
options.viaBotID = inlineResult.botID;
|
||||
options.queryID = queryID;
|
||||
options.resultID = resultID;
|
||||
|
||||
if (inlineResult.send_message._ == 'botInlineMessageText') {
|
||||
options.entities = inlineResult.send_message.entities;
|
||||
AppMessagesManager.sendText(peerID, inlineResult.send_message.message, options);
|
||||
} else {
|
||||
var caption = '';
|
||||
if (inlineResult.send_message._ == 'botInlineMessageMediaAuto') {
|
||||
caption = inlineResult.send_message.caption;
|
||||
}
|
||||
var inputMedia = false;
|
||||
if (inlineResult._ == 'botInlineMediaResultDocument') {
|
||||
var doc = inlineResult.document;
|
||||
inputMedia = {
|
||||
_: 'inputMediaDocument',
|
||||
id: {_: 'inputDocument', id: doc.id, access_hash: doc.access_hash},
|
||||
caption: caption
|
||||
};
|
||||
}
|
||||
else if (inlineResult._ == 'botInlineMediaResultPhoto') {
|
||||
var photo = inlineResult.photo;
|
||||
inputMedia = {
|
||||
_: 'inputMediaPhoto',
|
||||
id: {_: 'inputPhoto', id: photo.id, access_hash: photo.access_hash},
|
||||
caption: caption
|
||||
};
|
||||
}
|
||||
if (!inputMedia) {
|
||||
inputMedia = {
|
||||
_: 'messageMediaPending',
|
||||
type: inlineResult.type,
|
||||
file_name: inlineResult.title || inlineResult.content_url || inlineResult.url,
|
||||
size: 0,
|
||||
progress: {percent: 30, total: 0}
|
||||
};
|
||||
}
|
||||
AppMessagesManager.sendOther(peerID, inputMedia, options);
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
.service('ApiUpdatesManager', function ($rootScope, MtpNetworkerFactory, AppUsersManager, AppChatsManager, AppPeersManager, MtpApiManager) {
|
||||
@ -2828,6 +3060,9 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
}
|
||||
|
||||
function addChannelState (channelID, pts) {
|
||||
if (!pts) {
|
||||
throw new Error('Add channel state without pts ' + channelID);
|
||||
}
|
||||
if (channelStates[channelID] === undefined) {
|
||||
channelStates[channelID] = {
|
||||
pts: pts,
|
||||
@ -2842,9 +3077,6 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
|
||||
function getChannelState (channelID, pts) {
|
||||
if (channelStates[channelID] === undefined) {
|
||||
if (!pts) {
|
||||
throw new Error('Get channel empty state without pts ' + channelID);
|
||||
}
|
||||
addChannelState(channelID, pts);
|
||||
}
|
||||
return channelStates[channelID];
|
||||
@ -3997,7 +4229,11 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
type: 'JUMP_EXT_URL',
|
||||
url: url
|
||||
}).then(function () {
|
||||
window.open(url, '_blank');
|
||||
var target = '_blank';
|
||||
if (url.search('https://telegram.me/') === 0) {
|
||||
target = '_self';
|
||||
}
|
||||
window.open(url, target);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
@ -4142,4 +4378,4 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
start: start,
|
||||
shareUrl: shareUrl
|
||||
};
|
||||
})
|
||||
})
|
@ -420,20 +420,56 @@ a {
|
||||
display: block;
|
||||
border-radius: 100%;
|
||||
}
|
||||
.progress-arc circle {
|
||||
stroke-dashoffset: 0;
|
||||
stroke: rgba(0,0,0,0.3);
|
||||
stroke-width: 3px;
|
||||
}
|
||||
.progress-arc .progress-arc-bar {
|
||||
stroke: #FFF;
|
||||
stroke-dashoffset: 0;
|
||||
transform-origin: center center;
|
||||
transition: stroke-dasharray 500ms linear;
|
||||
fill: transparent;
|
||||
|
||||
-webkit-animation: infinite_rotation 2s linear infinite;
|
||||
-moz-animation: infinite_rotation 2s linear infinite;
|
||||
-ms-animation: infinite_rotation 2s linear infinite;
|
||||
animation: infinite_rotation 2s linear infinite;
|
||||
.progress-arc-intermediate & {
|
||||
stroke: #68a4d1;
|
||||
|
||||
-webkit-animation: infinite_rotation 0.8s linear infinite;
|
||||
-moz-animation: infinite_rotation 0.8s linear infinite;
|
||||
-ms-animation: infinite_rotation 0.8s linear infinite;
|
||||
animation: infinite_rotation 0.8s linear infinite;
|
||||
}
|
||||
|
||||
.composer_progress_icon & {
|
||||
stroke: rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.progress-arc-percent & {
|
||||
stroke: #FFF;
|
||||
stroke: rgba(255,255,255,0.95);
|
||||
|
||||
transition: stroke-dasharray 500ms linear;
|
||||
|
||||
-webkit-animation: infinite_rotation 2s linear infinite;
|
||||
-moz-animation: infinite_rotation 2s linear infinite;
|
||||
-ms-animation: infinite_rotation 2s linear infinite;
|
||||
animation: infinite_rotation 2s linear infinite;
|
||||
}
|
||||
}
|
||||
.stop0 {
|
||||
stop-opacity: 1.0;
|
||||
stop-color: #68a4d1;
|
||||
.composer_progress_icon & {
|
||||
stop-color: rgba(0,0,0,0.3);
|
||||
}
|
||||
}
|
||||
.stop60 {
|
||||
stop-opacity: 1.0;
|
||||
stop-color: #68a4d1;
|
||||
.composer_progress_icon & {
|
||||
stop-color: rgba(0,0,0,0.3);
|
||||
}
|
||||
}
|
||||
.stop100 {
|
||||
stop-opacity: 0.0;
|
||||
stop-color: #68a4d1;
|
||||
.composer_progress_icon & {
|
||||
stop-color: rgba(0,0,0,0.3);
|
||||
}
|
||||
}
|
||||
|
||||
/* Infinite rotation */
|
||||
@ -926,13 +962,14 @@ a.tg_radio_on:hover i.icon-radio {
|
||||
background-position: -5px -10px;
|
||||
}
|
||||
.icon-tg-title {
|
||||
width: 63px;
|
||||
height: 16px;
|
||||
width: 62px;
|
||||
height: 14px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
|
||||
.image-2x('../img/Telegram.png', 63px, 16px);
|
||||
background-image: url('../img/Telegram.svg');
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0 0;
|
||||
margin-top: 1px;
|
||||
}
|
||||
.login_head_submit_wrap,
|
||||
.login_head_submit_progress {
|
||||
@ -1392,7 +1429,8 @@ a.im_dialog_selected {
|
||||
}
|
||||
|
||||
.im_history {
|
||||
padding: 20px 0 0 0;
|
||||
// padding: 20px 0 0 0;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
}
|
||||
.im_message_unread_split {
|
||||
@ -1403,12 +1441,14 @@ a.im_dialog_selected {
|
||||
margin: 10px 0;
|
||||
}
|
||||
.im_message_author,
|
||||
.im_message_fwd_author {
|
||||
.im_message_fwd_author,
|
||||
.im_message_via_author {
|
||||
color: #3a6d99;
|
||||
font-weight: bold;
|
||||
}
|
||||
.non_osx .im_message_author,
|
||||
.non_osx .im_message_fwd_author {
|
||||
.non_osx .im_message_fwd_author,
|
||||
.non_osx .im_message_via_author {
|
||||
font-size: 12px;
|
||||
}
|
||||
.im_message_author_via {
|
||||
@ -1505,6 +1545,9 @@ div.im_message_video_thumb {
|
||||
|
||||
.image-2x('../img/icons/IconsetW.png', 42px, 1171px);
|
||||
background-position: 0 -590px;
|
||||
.is_2x & {
|
||||
background-position: 0 -591px;
|
||||
}
|
||||
}
|
||||
|
||||
.im_message_geopoint {
|
||||
@ -1999,6 +2042,10 @@ img.im_message_document_thumb {
|
||||
padding: 0 0 20px 10px;
|
||||
}
|
||||
|
||||
.im_message_date {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.im_message_author,
|
||||
div.im_message_body {
|
||||
display: block;
|
||||
@ -2245,6 +2292,37 @@ a.im_message_fwd_photo {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.im_history_loading {
|
||||
width: 60px;
|
||||
margin: 0 auto;
|
||||
visibility: hidden;
|
||||
|
||||
&.vertical-aligned {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
.im_history_loading_more {
|
||||
display: block;
|
||||
width: 26px;
|
||||
margin: 0 auto;
|
||||
padding: 20px 0 0;
|
||||
visibility: hidden;
|
||||
|
||||
&.im_history_loading_more_active {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
.im_history_loading_less {
|
||||
display: block;
|
||||
width: 26px;
|
||||
margin: 0 auto;
|
||||
visibility: hidden;
|
||||
|
||||
&.im_history_loading_less_active {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
.im_send_panel_wrap {
|
||||
margin: 0 auto;
|
||||
@ -2293,6 +2371,22 @@ textarea.im_message_field {
|
||||
height: 50px;
|
||||
resize: none;
|
||||
}
|
||||
.im_inline_placeholder_wrap {
|
||||
position: absolute;
|
||||
margin-top: 2px;
|
||||
white-space: nowrap;
|
||||
pointer-events: none;
|
||||
display: none;
|
||||
}
|
||||
.im_inline_placeholder_wrap.active {
|
||||
display: block;
|
||||
}
|
||||
.im_inline_placeholder_prefix {
|
||||
visibility: hidden;
|
||||
}
|
||||
.im_inline_placeholder {
|
||||
color: #9aa2ab;
|
||||
}
|
||||
|
||||
.icon-online {
|
||||
background: #6ec26d;
|
||||
@ -2423,7 +2517,27 @@ img.img_fullsize {
|
||||
}
|
||||
|
||||
/* Message composer */
|
||||
.composer_progress_icon {
|
||||
display: block;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
right: 3px;
|
||||
top: 2px;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
margin-top: 1px;
|
||||
transition: opacity cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.2s;
|
||||
pointer-events: none;
|
||||
|
||||
.composer_progress_enabled & {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.composer_emoji_insert_btn {
|
||||
opacity: 1;
|
||||
display: block;
|
||||
position: absolute;
|
||||
right: 3px;
|
||||
@ -2434,7 +2548,13 @@ img.img_fullsize {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
margin-top: 1px;
|
||||
transition: opacity cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.2s;
|
||||
|
||||
.composer_progress_enabled & {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-emoji {
|
||||
display: inline-block;
|
||||
width: 22px;
|
||||
@ -2757,6 +2877,7 @@ a.composer_emoji_btn {
|
||||
border-radius: 0;
|
||||
margin-top: -5px;
|
||||
margin-left: -1px;
|
||||
width: 180px;
|
||||
}
|
||||
|
||||
.composer_dropdown {
|
||||
@ -2780,9 +2901,10 @@ a.composer_emoji_btn {
|
||||
}
|
||||
|
||||
li a:hover,
|
||||
li a.composer_autocomplete_option_active {
|
||||
li.composer_autocomplete_option_active a {
|
||||
color: #52719a;
|
||||
background: #f2f6fa;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2802,7 +2924,7 @@ a.composer_emoji_btn {
|
||||
|
||||
.composer_dropdown {
|
||||
li a:hover .composer_user_mention,
|
||||
li a.composer_autocomplete_option_active .composer_user_mention {
|
||||
li.composer_autocomplete_option_active a .composer_user_mention {
|
||||
color: #698192;
|
||||
}
|
||||
}
|
||||
@ -2861,7 +2983,7 @@ a.composer_emoji_btn {
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
a.composer_command_option:hover .composer_command_desc,
|
||||
a.composer_command_option.composer_autocomplete_option_active .composer_command_desc {
|
||||
.composer_autocomplete_option_active a.composer_command_option .composer_command_desc {
|
||||
color: #698192;
|
||||
}
|
||||
.composer_command_desc .emoji {
|
||||
@ -3031,6 +3153,64 @@ _:-ms-lang(x), .composer_rich_textarea:empty:focus:before {
|
||||
}
|
||||
}
|
||||
|
||||
.inline_results_wrap {
|
||||
line-height: 0;
|
||||
}
|
||||
.inline_result_wrap {
|
||||
display: block;
|
||||
}
|
||||
.inline_result_gif,
|
||||
.inline_result_photo {
|
||||
display: inline-block;
|
||||
}
|
||||
.inline_result_article {
|
||||
display: block;
|
||||
}
|
||||
.inline_article_thumb_wrap {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
margin-right: 10px;
|
||||
pointer-events: none;
|
||||
}
|
||||
.inline_article_thumb {
|
||||
max-width: 50px;
|
||||
max-height: 50px;
|
||||
line-height: 0;
|
||||
}
|
||||
.inline_article_thumb_initials {
|
||||
background: rgba(0,0,0, 0.05);
|
||||
line-height: 50px;
|
||||
text-align: center;
|
||||
font-size: 25px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.inline_article_content_wrap {
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
}
|
||||
.inline_article_title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
.composer_dropdown > li.inline_result_gif > a,
|
||||
.composer_dropdown > li.inline_result_photo > a {
|
||||
padding: 0;
|
||||
line-height: 0;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
}
|
||||
.inline_result_gif .img_gif_video,
|
||||
.inline_result_photo .inline_result_photo_image {
|
||||
object-fit: cover;
|
||||
}
|
||||
.inline_result_gif_mtproto,
|
||||
.inline_result_gif_http,
|
||||
.inline_result_photo_mtproto,
|
||||
.inline_result_photo_http {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
||||
.error_modal_window {
|
||||
.modal-dialog {
|
||||
@ -3553,64 +3733,83 @@ h5 {
|
||||
}
|
||||
|
||||
/* Gif documents */
|
||||
.img_gif_with_progress_wrap {
|
||||
.img_gif_image_wrap {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
float: left;
|
||||
margin-top: 3px;
|
||||
max-width: 100%;
|
||||
}
|
||||
.img_gif_meta {
|
||||
background: rgba(0,0,0,0.3);
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
line-height: 0;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
margin: 0 auto;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-left: -20px;
|
||||
margin-top: -20px;
|
||||
pointer-events: none;
|
||||
}
|
||||
.img_gif_label {
|
||||
font-weight: bold;
|
||||
color: #FFF;
|
||||
display: block;
|
||||
line-height: 40px;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
}
|
||||
.icon-cancel {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-left: -9px;
|
||||
margin-top: -1px;
|
||||
|
||||
.icon-bar {
|
||||
display: block;
|
||||
width: 18px;
|
||||
height: 2px;
|
||||
background: #FFF;
|
||||
transform-origin: 50% 50%;
|
||||
|
||||
&:first-child {
|
||||
.transform(rotate(-45deg));
|
||||
}
|
||||
&:last-child {
|
||||
.transform(translate3d(0,-2px,0) rotate(45deg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.img_gif_thumb {
|
||||
-webkit-filter: blur(3px);
|
||||
-moz-filter: blur(3px);
|
||||
-o-filter: blur(3px);
|
||||
-ms-filter: blur(3px);
|
||||
filter: blur(3px);
|
||||
-webkit-filter: blur(2px);
|
||||
-moz-filter: blur(2px);
|
||||
-o-filter: blur(2px);
|
||||
-ms-filter: blur(2px);
|
||||
filter: blur(2px);
|
||||
filter: progid:DXImageTransform.Microsoft.Blur(PixelRadius='3');
|
||||
margin: -1px;
|
||||
padding: 1px;
|
||||
transform-origin: center center;
|
||||
-webkit-transform-origin: center center;
|
||||
-webkit-transform: scale(1.02, 1.02);
|
||||
transform: scale(1.02, 1.02);
|
||||
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
.img_gif_image {
|
||||
max-width: 100%;
|
||||
}
|
||||
.img_gif_info_wrap {
|
||||
color: #fff;
|
||||
font-size: 10px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 4px;
|
||||
}
|
||||
.img_gif_label,
|
||||
.img_gif_size {
|
||||
padding: 1px 8px;
|
||||
background: rgba(0,0,0,0.5);
|
||||
border-radius: 3px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.img_gif_progress_wrap {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
||||
.tg_progress {
|
||||
background: rgba(0,0,0, 0.6);
|
||||
border-color: rgba(0,0,0, 0.6);
|
||||
border-width: 8px;
|
||||
height: 18px;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
background: #fff;
|
||||
height: 2px;
|
||||
}
|
||||
.img_gif_meta_contents {
|
||||
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.2s;
|
||||
}
|
||||
.img_gif_meta_contents.ng-leave.ng-leave-active,
|
||||
.img_gif_meta_contents.ng-enter {
|
||||
opacity: 0;
|
||||
}
|
||||
.img_gif_meta_contents.ng-leave,
|
||||
.img_gif_meta_contents.ng-enter.ng-enter-active {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.countries_modal_window {
|
||||
|
@ -748,7 +748,6 @@ a.footer_link.active:active {
|
||||
line-height: 18px;
|
||||
width: 100%;
|
||||
height: 39px;
|
||||
padding: 13px 0 8px;
|
||||
overflow: hidden;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
@ -758,7 +757,7 @@ a.footer_link.active:active {
|
||||
color: #999;
|
||||
max-width: 556px;
|
||||
margin: 0 auto;
|
||||
padding: 0 81px 0 85px;
|
||||
padding: 13px 81px 8px 85px;
|
||||
|
||||
a.im_history_typing_author {
|
||||
color: #999;
|
||||
@ -767,6 +766,10 @@ a.footer_link.active:active {
|
||||
}
|
||||
}
|
||||
|
||||
.im_history_loading_less {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
/* Contacts modal */
|
||||
.contacts_modal {
|
||||
&_window {
|
||||
|
27
app/partials/desktop/composer_dropdown.html
Normal file
27
app/partials/desktop/composer_dropdown.html
Normal file
@ -0,0 +1,27 @@
|
||||
<div ng-switch="type">
|
||||
|
||||
<ul ng-switch-when="mentions" class="composer_dropdown">
|
||||
<li ng-repeat="user in mentionUsers">
|
||||
<a class="composer_mention_option" data-mention="{{user.username}}">
|
||||
<span class="composer_user_photo" my-peer-photolink="user.id" img-class="composer_user_photo"></span>
|
||||
<span class="composer_user_name" ng-bind-html="user.rFullName"></span>
|
||||
<span class="composer_user_mention" ng-bind="'@' + user.username"></span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul ng-switch-when="commands" class="composer_dropdown">
|
||||
<li ng-repeat="command in commands track by (command.botID + command.value)">
|
||||
<a class="composer_command_option" data-command="{{command.value}}">
|
||||
<span class="composer_user_photo" my-peer-photolink="command.botID" img-class="composer_user_photo"></span>
|
||||
<span class="composer_command_value" ng-bind="command.value"></span>
|
||||
<span class="composer_command_desc" ng-bind-html="command.rDescription"></span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul ng-switch-when="emoji" my-emoji-suggestions="emojiCodes" class="composer_dropdown"></ul>
|
||||
|
||||
<div ng-switch-when="inline" my-inline-results="botResults"></div>
|
||||
|
||||
</div>
|
@ -3,11 +3,14 @@
|
||||
<div class="img_gif_image_wrap">
|
||||
|
||||
<div class="img_gif_meta" ng-show="!isActive" ng-switch="document.progress.enabled">
|
||||
<div ng-switch-when="true" my-arc-progress="document.progress.percent"></div>
|
||||
<div ng-switch-default class="img_gif_info_wrap">
|
||||
<div class="img_gif_label pull-left">GIF</div>
|
||||
<div ng-if="!document.downloaded" class="img_gif_size pull-right" ng-bind="::document.size | formatSize"></div>
|
||||
<div ng-switch-when="true" class="img_gif_meta_contents">
|
||||
<i class="icon icon-cancel">
|
||||
<i class="icon icon-bar"></i>
|
||||
<i class="icon icon-bar"></i>
|
||||
</i>
|
||||
<div my-arc-progress="document.progress.percent"></div>
|
||||
</div>
|
||||
<div ng-switch-default class="img_gif_label noselect img_gif_meta_contents">GIF</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="document.url" ng-show="document.downloaded && isActive" ng-switch="document.mime_type == 'video/mp4'">
|
||||
|
@ -90,8 +90,8 @@
|
||||
<div ng-switch-default class="im_history_not_selected" my-vertical-position="0.35" padding="true" my-i18n="im_select_a_chat"></div>
|
||||
</div>
|
||||
|
||||
<div ng-show="!state.notSelected && !state.loaded" class="im_history_not_selected" my-vertical-position="0.35" padding="true">
|
||||
<my-i18n msgid="im_loading_history"></my-i18n><span my-loading-dots></span>
|
||||
<div ng-show="!state.notSelected && !state.loaded" class="im_history_loading" my-vertical-position="0.35" padding="true">
|
||||
<div my-arc-progress stroke="5" width="60"></div>
|
||||
</div>
|
||||
|
||||
<div ng-show="state.loaded">
|
||||
@ -103,14 +103,18 @@
|
||||
|
||||
<div class="im_history_scrollable">
|
||||
<div class="im_history" ng-class="{im_history_selectable: !historyState.botActions, im_history_select_active: historyState.selectActions}">
|
||||
<div ng-if="state.empty" class="im_history_empty" ng-switch="state.mayBeHasMore" my-vertical-position="0.25" padding="true">
|
||||
<span ng-switch-when="true">
|
||||
<my-i18n msgid="im_loading_history"></my-i18n><span my-loading-dots></span>
|
||||
</span>
|
||||
<span ng-switch-default my-i18n="im_no_messages"></span>
|
||||
|
||||
<div class="im_history_empty_wrap" ng-show="state.empty" ng-switch="state.mayBeHasMore">
|
||||
<div ng-switch-when="true" class="im_history_loading" my-vertical-position="0.25" padding="true">
|
||||
<div my-arc-progress stroke="5" width="60"></div>
|
||||
</div>
|
||||
<div ng-switch-default class="im_history_empty" my-vertical-position="0.25" padding="true" my-i18n="im_no_messages"></div>
|
||||
</div>
|
||||
|
||||
<div class="im_history_messages" ng-class="{im_history_messages_group: historyPeer.id < 0}">
|
||||
<div class="im_history_loading_more" ng-class="{im_history_loading_more_active: state.moreActive}">
|
||||
<div my-arc-progress stroke="3" width="26"></div>
|
||||
</div>
|
||||
<div class="im_history_messages_peer" ng-show="peerHistory.peerID == historyPeer.id" ng-repeat="peerHistory in peerHistories">
|
||||
<div class="im_history_message_wrap" my-message ng-repeat="historyMessage in peerHistory.messages"></div>
|
||||
</div>
|
||||
@ -118,9 +122,12 @@
|
||||
|
||||
</div>
|
||||
|
||||
<div class="im_history_typing_wrap">
|
||||
<div class="im_history_typing_wrap" ng-switch="historyState.skipped">
|
||||
|
||||
<div class="im_history_typing" ng-show="historyState.typing.length > 0 && !historyFilter.mediaType && !state.empty" ng-switch="historyState.typing.length" my-i18n>
|
||||
<div ng-switch-when="true" class="im_history_loading_less" ng-class="{im_history_loading_less_active: state.lessActive}">
|
||||
<div my-arc-progress stroke="3" width="26"></div>
|
||||
</div>
|
||||
<div ng-switch-default class="im_history_typing" ng-show="historyState.typing.length > 0 && !historyFilter.mediaType && !state.empty" ng-switch="historyState.typing.length" my-i18n>
|
||||
<span ng-switch-when="1" my-i18n-format="im_one_typing"></span>
|
||||
<span ng-switch-when="2" my-i18n-format="im_two_typing"></span>
|
||||
<span ng-switch-default my-i18n-format="im_many_typing"></span>
|
||||
@ -175,7 +182,9 @@
|
||||
</a>
|
||||
<a class="pull-left im_panel_own_photo" my-peer-photolink="draftMessage.isBroadcast ? historyPeer.id : ownID" img-class="im_panel_own_photo" watch="true" ng-click="openSettings()" no-open="true"></a>
|
||||
|
||||
<form my-send-form draft-message="draftMessage" mentions="mentions" commands="commands" class="im_send_form" ng-class="{im_send_form_empty: !draftMessage.text.length}">
|
||||
<form my-send-form draft-message="draftMessage" mentions="mentions" commands="commands" class="im_send_form" ng-class="{im_send_form_empty: !draftMessage.text.length, composer_progress_enabled: draftMessage.inlineProgress}">
|
||||
|
||||
<div class="im_send_form_inline_results" my-inline-results="inlineResults"></div>
|
||||
|
||||
<div class="im_send_reply_wrap" ng-if="draftMessage.replyToMessage != null">
|
||||
<a class="im_send_reply_cancel" ng-mousedown="draftMessage.replyClear()"><i class="icon icon-reply-bar"></i><i class="icon icon-reply-bar"></i></a>
|
||||
@ -189,23 +198,24 @@
|
||||
|
||||
<div class="im_send_field_wrap" ng-class="historyState.replyKeyboard._ == 'replyKeyboardMarkup' ? 'im_send_field_wrap_2ndbtn' : ''">
|
||||
<a class="composer_emoji_insert_btn"><i class="icon icon-emoji"></i></a>
|
||||
<div class="composer_progress_icon" my-arc-progress width="22" stroke="2.5"></div>
|
||||
<a class="composer_command_btn" ng-show="!historyState.replyKeyboard && commands.list.length > 0 && (!draftMessage.text.length || draftMessage.text[0] == '/')" ng-mousedown="toggleSlash($event)" ng-class="draftMessage.text[0] == '/' ? 'active' : ''"><i class="icon icon-slash"></i></a>
|
||||
<a class="composer_keyboard_btn" ng-show="historyState.replyKeyboard._ == 'replyKeyboardMarkup'" ng-mousedown="replyKeyboardToggle($event)" ng-class="!historyState.replyKeyboard.pFlags.hidden ? 'active' : ''"><i class="icon icon-keyboard"></i></a>
|
||||
|
||||
<div class="im_send_dropbox_wrap" my-i18n="im_photos_drop_text"></div>
|
||||
<textarea ng-model="draftMessage.text" class="form-control im_message_field no_outline" dir="auto"></textarea>
|
||||
<textarea ng-model="draftMessage.text" class="form-control im_message_field no_outline" dir="auto" ng-trim="false"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="im_send_buttons_wrap clearfix">
|
||||
<button type="submit" class="btn btn-md im_submit" my-i18n="im_submit_message"></button>
|
||||
|
||||
<div class="im_attach pull-left">
|
||||
<input type="file" class="im_attach_input" size="28" multiple="true" title="{{'im_attach_file_title' | i18n}}" />
|
||||
<input type="file" class="im_attach_input" size="28" multiple="multiple" title="{{'im_attach_file_title' | i18n}}" />
|
||||
<i class="icon icon-paperclip"></i>
|
||||
</div>
|
||||
|
||||
<div class="im_media_attach pull-left">
|
||||
<input type="file" class="im_media_attach_input" size="28" multiple="true" accept="image/*, video/*, audio/*" title="{{'im_media_attach_title' | i18n}}"/>
|
||||
<input type="file" class="im_media_attach_input" size="28" multiple="multiple" accept="image/*, video/*, audio/*" title="{{'im_media_attach_title' | i18n}}"/>
|
||||
<i class="icon icon-camera"></i>
|
||||
</div>
|
||||
|
||||
@ -234,4 +244,4 @@
|
||||
|
||||
</div>
|
||||
|
||||
<div class="footer_wrap footer_empty"></div>
|
||||
<div class="footer_wrap footer_empty"></div>
|
||||
|
53
app/partials/desktop/inline_results.html
Normal file
53
app/partials/desktop/inline_results.html
Normal file
@ -0,0 +1,53 @@
|
||||
<ul class="inline_results_wrap composer_dropdown">
|
||||
<li class="inline_result_wrap" ng-class="'inline_result_' + result.type" ng-repeat="result in botResults.results track by result.qID" ng-switch="result.type">
|
||||
|
||||
<a ng-switch-when="gif" class="img_gif_with_progress_wrap" data-inlineid="{{result.qID}}" ng-style="::{width: result.thumbW, height: result.thumbH}" ng-switch="result._">
|
||||
<div ng-switch-when="botInlineMediaResultDocument" ng-switch="result.document.url !== undefined" class="inline_result_gif_mtproto">
|
||||
<div ng-switch-when="true" ng-switch="result.document.mime_type == 'video/mp4'">
|
||||
<video ng-switch-when="true" width="{{result.thumbW}}" height="{{result.thumbH}}" loop autoplay class="img_gif_video">
|
||||
<source ng-src="{{result.document.url}}" type="video/mp4">
|
||||
</video>
|
||||
<img ng-switch-default class="img_gif_image" ng-src="{{result.document.url}}" width="{{result.thumbW}}" height="{{result.thumbH}}" />
|
||||
</div>
|
||||
<div ng-switch-default class="img_gif_image_wrap">
|
||||
<img class="img_gif_thumb" my-load-thumb thumb="result.document.thumb" width="{{result.thumbW}}" height="{{result.thumbH}}" />
|
||||
</div>
|
||||
</div>
|
||||
<div ng-switch-default ng-switch="result.contentUrl !== undefined" class="inline_result_gif_http">
|
||||
<div ng-switch-when="true" ng-switch="result.content_type == 'video/mp4'">
|
||||
<video ng-switch-when="true" width="{{result.thumbW}}" height="{{result.thumbH}}" loop autoplay class="img_gif_video">
|
||||
<source ng-src="{{result.contentUrl}}" type="video/mp4">
|
||||
</video>
|
||||
<img ng-switch-default class="img_gif_image" ng-src="{{result.contentUrl}}" width="{{result.thumbW}}" height="{{result.thumbH}}" />
|
||||
</div>
|
||||
<img ng-switch-default ng-if="result.thumbUrl !== undefined" class="img_gif_thumb" width="{{result.thumbW}}" height="{{result.thumbH}}" ng-src="{{result.thumbUrl}}" />
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a ng-switch-when="photo" data-inlineid="{{result.qID}}" ng-style="::{width: result.thumbW, height: result.thumbH}" ng-switch="result._">
|
||||
<div ng-switch-when="botInlineMediaResultPhoto" class="inline_result_photo_mtproto">
|
||||
<img
|
||||
class="inline_result_photo_image"
|
||||
my-load-thumb
|
||||
thumb="result.thumb"
|
||||
/>
|
||||
</div>
|
||||
<div ng-switch-default ng-switch="result.contentUrl !== undefined" class="inline_result_photo_http">
|
||||
<img ng-switch-default ng-if="result.thumbUrl !== undefined" class="inline_result_photo_image" width="{{result.thumbW}}" height="{{result.thumbH}}" ng-src="{{result.thumbUrl}}" />
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a ng-switch-default class="inline_result_article clearfix" data-inlineid="{{result.qID}}">
|
||||
<div class="inline_article_thumb_wrap pull-left" ng-switch="result.thumbUrl !== undefined">
|
||||
<img ng-switch-when="true" class="inline_article_thumb" ng-src="{{result.thumbUrl}}"/>
|
||||
<div ng-switch-default class="inline_article_thumb_initials" ng-bind="result.initials"></div>
|
||||
</div>
|
||||
<div class="inline_article_content_wrap">
|
||||
<div class="inline_article_title" ng-if="::result.title.length > 0" ng-bind-html="::result.rTitle"></div>
|
||||
<div class="inline_article_description" ng-if="::result.description.length > 0" ng-bind-html="::result.rDescription"></div>
|
||||
<div class="inline_article_url" ng-if="::result.url.length > 0" ng-bind="::result.url"></div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
</ul>
|
@ -39,12 +39,12 @@
|
||||
<i class="icon-message-views"></i><span class="im_message_views_cnt" my-message-views="historyMessage.mid"></span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="im_message_date" ng-bind="::historyMessage.date | time"></span>
|
||||
<span class="im_message_date clickable" ng-bind="::historyMessage.date | time"></span>
|
||||
</div>
|
||||
|
||||
<div class="im_message_body" ng-class="::{im_message_body_media: historyMessage._ == 'message' && historyMessage.media ? true : false}">
|
||||
|
||||
<a class="im_message_author" my-peer-link="historyMessage.fromID" short="historyMessage.toID > 0" color="historyMessage.toID < 0" no-watch="true"></a><span ng-if="::historyMessage.viaBotID && !historyMessage.fwdFromID" class="im_message_author_via" my-i18n="message_via_bot"><my-i18n-param name="bot"><a class="im_message_fwd_author" my-peer-link="historyMessage.viaBotID" username="true" no-watch="true"></a></my-i18n-param></span>
|
||||
<a class="im_message_author" my-peer-link="historyMessage.fromID" short="historyMessage.toID > 0" color="historyMessage.toID < 0" no-watch="true"></a><span ng-if="::historyMessage.viaBotID && !historyMessage.fwdFromID" class="im_message_author_via" my-i18n="message_via_bot"><my-i18n-param name="bot"><a class="im_message_fwd_author" my-peer-link="historyMessage.viaBotID" username="true" no-watch="true" ng-click="selectInlineBot(historyMessage.viaBotID, $event)"></a></my-i18n-param></span>
|
||||
|
||||
<a class="im_message_reply_wrap" my-reply-message="historyMessage.reply_to_msg" ng-if="::historyMessage.reply_to_mid"></a>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user