Browse Source

Improved inline bots

master
Igor Zhukov 9 years ago
parent
commit
1cee4855f5
  1. 16
      app/js/controllers.js
  2. 24
      app/js/directives.js
  3. 1
      app/js/lib/ng_utils.js
  4. 6
      app/js/lib/utils.js
  5. 12
      app/js/message_composer.js
  6. 36
      app/js/messages_manager.js
  7. 104
      app/js/services.js
  8. 4
      app/partials/desktop/reply_markup.html

16
app/js/controllers.js

@ -2348,6 +2348,22 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.$broadcast('ui_peer_draft'); $scope.$broadcast('ui_peer_draft');
}); });
} }
else if (attachment._ == 'inline_query') {
var mention = attachment.mention;
var query = attachment.query;
forceDraft = $scope.curDialog.peer;
$timeout(function () {
$scope.draftMessage.text = mention + ' ' + query;
$scope.$broadcast('ui_peer_draft', {
customSelection: [
mention + " " + query,
'',
''
]
});
}, 1000);
}
} }
function replySelect(messageID) { function replySelect(messageID) {

24
app/js/directives.js

@ -176,7 +176,7 @@ angular.module('myApp.directives', ['myApp.filters'])
} }
}) })
.directive('myMessageBody', function($compile, AppPeersManager, AppChatsManager, AppUsersManager, AppMessagesManager, RichTextProcessor) { .directive('myMessageBody', function($compile, AppPeersManager, AppChatsManager, AppUsersManager, AppMessagesManager, AppInlineBotsManager, RichTextProcessor) {
var messageMediaCompiled = $compile('<div class="im_message_media" my-message-media="media" message-id="messageId"></div>'); var messageMediaCompiled = $compile('<div class="im_message_media" my-message-media="media" message-id="messageId"></div>');
var messageKeyboardCompiled = $compile('<div class="im_message_keyboard" my-inline-reply-markup="markup"></div>'); var messageKeyboardCompiled = $compile('<div class="im_message_keyboard" my-inline-reply-markup="markup"></div>');
@ -246,12 +246,20 @@ angular.module('myApp.directives', ['myApp.filters'])
}); });
scope.$on('reply_inline_button_press', function (e, button) { scope.$on('reply_inline_button_press', function (e, button) {
AppMessagesManager.replyMarkupButtonPress(message.mid, button); switch (button._) {
case 'keyboardButtonSwitchInline':
AppInlineBotsManager.switchInlineButtonClick(message.mid, button);
break;
case 'keyboardButtonCallback':
AppInlineBotsManager.callbackButtonClick(message.mid, button);
break;
}
}); });
} }
function link ($scope, element, attrs) { function link ($scope, element, attrs) {
var message = $scope.message; var message = $scope.message;
message.dir = true;
var msgID = message.mid; var msgID = message.mid;
updateMessageText($scope, element, message); updateMessageText($scope, element, message);
@ -268,14 +276,18 @@ angular.module('myApp.directives', ['myApp.filters'])
} }
$scope.$on('message_edit', function (e, data) { $scope.$on('message_edit', function (e, data) {
if (data.mid != msgID) { // var message = $scope.message;
// message = $scope.$parent.$eval(attrs.myMessageBody);
message = AppMessagesManager.wrapForHistory(message.mid);
if (data.mid != message.mid) {
return; return;
} }
console.log('after edit', message); console.log('after edit', message.dir, message);
updateMessageText($scope, element, message); updateMessageText($scope, element, message);
updateMessageMedia($scope, element, message); updateMessageMedia($scope, element, message);
updateMessageKeyboard($scope, element, message); updateMessageKeyboard($scope, element, message);
$scope.$emit('ui_height'); $scope.$emit('ui_height');
message.dir = true;
}); });
} }
}) })
@ -323,7 +335,7 @@ angular.module('myApp.directives', ['myApp.filters'])
classPrefix: 'reply_markup', classPrefix: 'reply_markup',
maxHeight: 170 maxHeight: 170
}); });
$scope.buttonSend = function (button) { $scope.buttonClick = function (button) {
$scope.$emit('reply_button_press', button); $scope.$emit('reply_button_press', button);
} }
@ -458,7 +470,7 @@ angular.module('myApp.directives', ['myApp.filters'])
}; };
function link ($scope, element, attrs) { function link ($scope, element, attrs) {
$scope.buttonSend = function (button) { $scope.buttonClick = function (button) {
$scope.$emit('reply_inline_button_press', button); $scope.$emit('reply_inline_button_press', button);
} }
} }

1
app/js/lib/ng_utils.js

@ -1742,7 +1742,6 @@ angular.module('izhukov.utils', [])
} }
function wrapUrl(url, unsafe) { function wrapUrl(url, unsafe) {
var url = entity.url || entityText;
if (!url.match(/^https?:\/\//i)) { if (!url.match(/^https?:\/\//i)) {
url = 'http://' + url; url = 'http://' + url;
} }

6
app/js/lib/utils.js

@ -164,7 +164,10 @@ function getRichValue(field) {
lines.push(line.join('')); lines.push(line.join(''));
} }
return lines.join('\n'); var value = lines.join('\n');
value = value.replace(/\u00A0/g, ' ');
return value;
} }
function getRichValueWithCaret(field) { function getRichValueWithCaret(field) {
@ -197,6 +200,7 @@ function getRichValueWithCaret(field) {
if (caretPos != -1) { if (caretPos != -1) {
value = value.substr(0, caretPos) + value.substr(caretPos + 1); value = value.substr(0, caretPos) + value.substr(caretPos + 1);
} }
value = value.replace(/\u00A0/g, ' ');
return [value, caretPos]; return [value, caretPos];
} }

12
app/js/message_composer.js

@ -978,7 +978,6 @@ MessageComposer.prototype.checkAutocomplete = function (forceFull) {
if (value && if (value &&
this.curInlineResults && this.curInlineResults &&
this.curInlineResults.text == value) { this.curInlineResults.text == value) {
console.trace(dT(), value, this.curInlineResults);
this.showInlineSuggestions(this.curInlineResults); this.showInlineSuggestions(this.curInlineResults);
return; return;
}; };
@ -1335,7 +1334,6 @@ MessageComposer.prototype.onChange = function (e) {
if (this.richTextareaEl) { if (this.richTextareaEl) {
delete this.keyupStarted; delete this.keyupStarted;
var richValue = getRichValue(this.richTextareaEl[0]); var richValue = getRichValue(this.richTextareaEl[0]);
richValue = richValue.replace(/\u00A0/g, ' ');
this.textareaEl.val(richValue).trigger('change'); this.textareaEl.val(richValue).trigger('change');
} }
this.updateInlinePlaceholder(); this.updateInlinePlaceholder();
@ -1390,13 +1388,18 @@ MessageComposer.prototype.setFocusedValue = function (parts) {
MessageComposer.prototype.getRichHtml = function (text) { MessageComposer.prototype.getRichHtml = function (text) {
return $('<div>').text(text).html().replace(/\n/g, '<br/>').replace(/:([A-Za-z0-9\-\+\*_]+?):/gi, (function (all, shortcut) { var html = $('<div>').text(text).html();
html = html.replace(/\n/g, '<br/>');
html = html.replace(/:([A-Za-z0-9\-\+\*_]+?):/gi, (function (all, shortcut) {
var code = EmojiHelper.shortcuts[shortcut]; var code = EmojiHelper.shortcuts[shortcut];
if (code !== undefined) { if (code !== undefined) {
return this.getEmojiHtml(code); return this.getEmojiHtml(code);
} }
return all; return all;
}).bind(this)); }).bind(this));
html = html.replace(/ /g, " \u00A0").replace(/^ | $/g, "\u00A0");
return html;
} }
@ -1471,7 +1474,8 @@ MessageComposer.prototype.showInlineSuggestions = function (botResults) {
} }
var self = this; var self = this;
if (self.autoCompleteScope.type == 'inline' && if (self.autoCompleteScope.type == 'inline' &&
self.autoCompleteScope.botResults == botResults) { self.autoCompleteScope.botResults == botResults &&
self.autocompleteShown) {
return; return;
} }
setZeroTimeout(function () { setZeroTimeout(function () {

36
app/js/messages_manager.js

@ -2176,18 +2176,6 @@ angular.module('myApp.services')
return messagesForHistory[msgID] = message; return messagesForHistory[msgID] = message;
} }
function replyMarkupButtonPress(id, button) {
var message = getMessage(id);
var peerID = getMessagePeer(message);
MtpApiManager.invokeApi('messages.getBotCallbackAnswer', {
peer: AppPeersManager.getInputPeerByID(peerID),
msg_id: getMessageLocalID(id),
data: button.data
}).then(function (callbackAnswer) {
console.info(callbackAnswer.message || 'empty answer');
});
}
function wrapReplyMarkup (replyMarkup) { function wrapReplyMarkup (replyMarkup) {
if (!replyMarkup || if (!replyMarkup ||
replyMarkup._ == 'replyKeyboardHide') { replyMarkup._ == 'replyKeyboardHide') {
@ -2208,6 +2196,9 @@ angular.module('myApp.services')
angular.forEach(replyMarkup.rows, function (markupRow) { angular.forEach(replyMarkup.rows, function (markupRow) {
angular.forEach(markupRow.buttons, function (markupButton) { angular.forEach(markupRow.buttons, function (markupButton) {
markupButton.rText = RichTextProcessor.wrapRichText(markupButton.text, {noLinks: true, noLinebreaks: true}); markupButton.rText = RichTextProcessor.wrapRichText(markupButton.text, {noLinks: true, noLinebreaks: true});
if (markupButton._ == 'keyboardButtonUrl') {
markupButton.pUrl = RichTextProcessor.wrapUrl(markupButton.url, true);
}
}) })
}); });
return replyMarkup; return replyMarkup;
@ -2800,21 +2791,20 @@ angular.module('myApp.services')
break; break;
} }
console.trace(dT(), 'edit message', mid, message); // console.trace(dT(), 'edit message', message);
saveMessages([message], true); saveMessages([message], true);
safeReplaceObject(messagesStorage[mid], message); safeReplaceObject(messagesStorage[mid], message);
messagesStorage[mid] = message;
if (messagesForHistory[mid] !== undefined) { var wasForHistory = messagesForHistory[mid];
var wasForHistory = messagesForHistory[mid]; if (wasForHistory !== undefined) {
delete messagesForHistory[mid]; delete messagesForHistory[mid];
var newForHistory = wrapForHistory(mid); safeReplaceObject(wasForHistory, wrapForHistory(mid));
// console.log('replacing', wasForHistory, 'with', newForHistory);
safeReplaceObject(wasForHistory, newForHistory);
messagesForHistory[mid] = newForHistory;
} }
$rootScope.$broadcast('message_edit', {peerID: peerID, id: message.id, mid: mid}); $rootScope.$broadcast('message_edit', {
peerID: peerID,
id: message.id,
mid: mid
});
break; break;
case 'updateReadHistoryInbox': case 'updateReadHistoryInbox':
@ -3085,6 +3075,7 @@ angular.module('myApp.services')
getHistory: getHistory, getHistory: getHistory,
getSearch: getSearch, getSearch: getSearch,
getMessage: getMessage, getMessage: getMessage,
getMessageLocalID: getMessageLocalID,
getReplyKeyboard: getReplyKeyboard, getReplyKeyboard: getReplyKeyboard,
readHistory: readHistory, readHistory: readHistory,
readMessages: readMessages, readMessages: readMessages,
@ -3096,7 +3087,6 @@ angular.module('myApp.services')
sendOther: sendOther, sendOther: sendOther,
forwardMessages: forwardMessages, forwardMessages: forwardMessages,
startBot: startBot, startBot: startBot,
replyMarkupButtonPress: replyMarkupButtonPress,
openChatInviteLink: openChatInviteLink, openChatInviteLink: openChatInviteLink,
convertMigratedPeer: convertMigratedPeer, convertMigratedPeer: convertMigratedPeer,
getMessagePeer: getMessagePeer, getMessagePeer: getMessagePeer,

104
app/js/services.js

@ -2402,7 +2402,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
} }
}) })
.service('AppInlineBotsManager', function ($rootScope, Storage, MtpApiManager, AppMessagesManager, AppDocsManager, AppPhotosManager, RichTextProcessor, AppUsersManager, AppPeersManager) { .service('AppInlineBotsManager', function ($rootScope, Storage, MtpApiManager, AppMessagesManager, AppDocsManager, AppPhotosManager, RichTextProcessor, AppUsersManager, AppPeersManager, PeersSelectService) {
var inlineResults = {}; var inlineResults = {};
@ -2411,6 +2411,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
regroupWrappedResults: regroupWrappedResults, regroupWrappedResults: regroupWrappedResults,
switchToPM: switchToPM, switchToPM: switchToPM,
checkSwitchReturn: checkSwitchReturn, checkSwitchReturn: checkSwitchReturn,
switchInlineButtonClick: switchInlineButtonClick,
callbackButtonClick: callbackButtonClick,
getInlineResults: getInlineResults, getInlineResults: getInlineResults,
getPopularBots: getPopularBots getPopularBots: getPopularBots
}; };
@ -2501,37 +2503,10 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
inlineResults[qID] = result; inlineResults[qID] = result;
}); });
console.log('res', botResults);
return botResults; return botResults;
}); });
} }
function switchToPM(fromPeerID, botID, startParam) {
var setHash = {};
var peerString = AppPeersManager.getPeerString(fromPeerID);
setHash['inline_switch_pm' + botID] = {peer: peerString, time: tsNow()};
Storage.set(setHash);
$rootScope.$broadcast('history_focus', {peerString: AppPeersManager.getPeerString(botID)});
AppMessagesManager.startBot(botID, 0, startParam);
}
function checkSwitchReturn(botID) {
var bot = AppUsersManager.getUser(botID);
if (!bot || !bot.pFlags.bot || !bot.bot_inline_placeholder) {
return qSync.when(false);
}
var key = 'inline_switch_pm' + botID;
return Storage.get(key).then(function (peerData) {
if (peerData) {
Storage.remove(key);
if (tsNow() - peerData.time < 3600000) {
return peerData.peerString;
}
}
return false;
});
}
function regroupWrappedResults (results, rowW, rowH) { function regroupWrappedResults (results, rowW, rowH) {
if (!results || if (!results ||
!results[0] || !results[0] ||
@ -2606,6 +2581,73 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}); });
} }
function switchToPM(fromPeerID, botID, startParam) {
var peerString = AppPeersManager.getPeerString(fromPeerID);
var setHash = {};
setHash['inline_switch_pm' + botID] = {peer: peerString, time: tsNow()};
Storage.set(setHash);
$rootScope.$broadcast('history_focus', {peerString: AppPeersManager.getPeerString(botID)});
AppMessagesManager.startBot(botID, 0, startParam);
}
function checkSwitchReturn(botID) {
var bot = AppUsersManager.getUser(botID);
if (!bot || !bot.pFlags.bot || !bot.bot_inline_placeholder) {
return qSync.when(false);
}
var key = 'inline_switch_pm' + botID;
return Storage.get(key).then(function (peerData) {
if (peerData) {
Storage.remove(key);
if (tsNow() - peerData.time < 3600000) {
return peerData.peer;
}
}
return false;
});
}
function switchInlineQuery(botID, toPeerString, query) {
$rootScope.$broadcast('history_focus', {
peerString: toPeerString,
attachment: {
_: 'inline_query',
mention: '@' + AppUsersManager.getUser(botID).username,
query: query
}
});
}
function switchInlineButtonClick(id, button) {
var message = AppMessagesManager.getMessage(id);
var botID = message.fromID;
return checkSwitchReturn(botID).then(function (retPeerString) {
if (retPeerString) {
return switchInlineQuery(botID, retPeerString, button.query);
}
PeersSelectService.selectPeer({
canSend: true
}).then(function (toPeerString) {
return switchInlineQuery(botID, toPeerString, button.query);
});
});
}
function callbackButtonClick(id, button) {
var message = AppMessagesManager.getMessage(id);
var botID = message.fromID;
var peerID = AppMessagesManager.getMessagePeer(message);
return MtpApiManager.invokeApi('messages.getBotCallbackAnswer', {
peer: AppPeersManager.getInputPeerByID(peerID),
msg_id: AppMessagesManager.getMessageLocalID(id),
data: button.data
}).then(function (callbackAnswer) {
console.info(callbackAnswer.message || 'empty answer');
});
}
function sendInlineResult (peerID, qID, options) { function sendInlineResult (peerID, qID, options) {
var inlineResult = inlineResults[qID]; var inlineResult = inlineResults[qID];
if (inlineResult === undefined) { if (inlineResult === undefined) {
@ -3063,6 +3105,10 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
curState.pts = update.pts; curState.pts = update.pts;
popPts = true; popPts = true;
} }
else if (update.pts_count) {
// console.warn(dT(), 'Duplicate update', update);
return false;
}
if (channelID && options.date && updatesState.date < options.date) { if (channelID && options.date && updatesState.date < options.date) {
updatesState.date = options.date; updatesState.date = options.date;
} }
@ -4228,7 +4274,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
} }
} }
else if (name === 'share' && data.blobs && data.blobs.length > 0) { else if (name === 'share' && data.blobs && data.blobs.length > 0) {
PeersSelectService.selectPeers({confirm_type: 'EXT_SHARE_PEER'}).then(function (peerStrings) { PeersSelectService.selectPeers({confirm_type: 'EXT_SHARE_PEER', canSend: true}).then(function (peerStrings) {
angular.forEach(peerStrings, function (peerString) { angular.forEach(peerStrings, function (peerString) {
var peerID = AppPeersManager.getPeerID(peerString); var peerID = AppPeersManager.getPeerID(peerString);
angular.forEach(data.blobs, function (blob) { angular.forEach(data.blobs, function (blob) {

4
app/partials/desktop/reply_markup.html

@ -2,8 +2,8 @@
<div class="reply_markup" ng-class="replyMarkup.splitCount ? 'reply_markup_h' + replyMarkup.splitCount : ''"> <div class="reply_markup" ng-class="replyMarkup.splitCount ? 'reply_markup_h' + replyMarkup.splitCount : ''">
<div class="reply_markup_row" ng-repeat="row in replyMarkup.rows"> <div class="reply_markup_row" ng-repeat="row in replyMarkup.rows">
<div class="reply_markup_button_wrap" ng-class="'reply_markup_button_w' + row.buttons.length" ng-repeat="button in row.buttons" ng-switch="button._"> <div class="reply_markup_button_wrap" ng-class="'reply_markup_button_w' + row.buttons.length" ng-repeat="button in row.buttons" ng-switch="button._">
<a ng-switch-when="keyboardButtonUrl" class="btn reply_markup_button" ng-bind-html="::button.rText" ng-click="buttonSend(button)"></a> <a ng-switch-when="keyboardButtonUrl" class="btn reply_markup_button" href="{{button.pUrl}}" ng-bind-html="::button.rText"></a>
<button ng-switch-default class="btn reply_markup_button" ng-bind-html="::button.rText" ng-click="buttonSend(button)"></button> <button ng-switch-default class="btn reply_markup_button" ng-bind-html="::button.rText" ng-click="buttonClick(button)"></button>
</div> </div>
</div> </div>
</div> </div>

Loading…
Cancel
Save