Browse Source

Channels improvements

Supported load important history
Added channel profile
master
Igor Zhukov 9 years ago
parent
commit
b0b5e2c75c
  1. BIN
      app/img/icons/ProfileIcons.png
  2. BIN
      app/img/icons/ProfileIcons_2x.png
  3. 282
      app/js/controllers.js
  4. 30
      app/js/directives.js
  5. 17
      app/js/locales/en-us.json
  6. 391
      app/js/services.js
  7. 15
      app/less/app.less
  8. 28
      app/partials/desktop/channel_edit_modal.html
  9. 136
      app/partials/desktop/channel_modal.html
  10. 26
      app/partials/desktop/chat_invite_link_modal.html
  11. 2
      app/partials/desktop/confirm_modal.html
  12. 2
      app/partials/desktop/dialog.html
  13. 2
      app/partials/desktop/im.html
  14. 14
      app/partials/desktop/message.html
  15. 2
      app/partials/desktop/reply_message.html
  16. 2
      app/partials/mobile/dialog.html
  17. 2
      app/partials/mobile/im.html
  18. 12
      app/partials/mobile/message.html

BIN
app/img/icons/ProfileIcons.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
app/img/icons/ProfileIcons_2x.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

282
app/js/controllers.js

@ -706,7 +706,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -706,7 +706,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.$on('history_delete', function (e, historyUpdate) {
for (var i = 0; i < $scope.dialogs.length; i++) {
if ($scope.dialogs[i].peerID == historyUpdate.peerID) {
if (historyUpdate.msgs[$scope.dialogs[i].id]) {
if (historyUpdate.msgs[$scope.dialogs[i].mid]) {
$scope.dialogs[i].deleted = true;
}
break;
@ -1490,7 +1490,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -1490,7 +1490,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
i, startPos, curMessageID;
for (i = 0; i < peerHistory.messages.length; i++) {
if (peerHistory.messages[i].id == lastSelectID) {
if (peerHistory.messages[i].mid == lastSelectID) {
startPos = i;
break;
}
@ -1498,7 +1498,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -1498,7 +1498,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
i = startPos;
while (peerHistory.messages[i] &&
(curMessageID = peerHistory.messages[i].id) != messageID) {
(curMessageID = peerHistory.messages[i].mid) != messageID) {
if (!$scope.selectedMsgs[curMessageID]) {
$scope.selectedMsgs[curMessageID] = true;
$scope.selectedCount++;
@ -1646,7 +1646,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -1646,7 +1646,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
return;
}
AppMessagesManager.sendText(peerID, button.text, {
replyToMsgID: peerID < 0 && replyKeyboard.id
replyToMsgID: peerID < 0 && replyKeyboard.mid
});
});
@ -1700,7 +1700,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -1700,7 +1700,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
!historyMessage.out &&
!(history.messages[history.messages.length - 2] || {}).unread) {
$scope.historyUnreadAfter = historyMessage.id;
$scope.historyUnreadAfter = historyMessage.mid;
unreadAfterIdle = true;
$scope.$broadcast('messages_unread_after');
}
@ -1740,7 +1740,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -1740,7 +1740,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
if (len > 10) {
if (curPeer) {
if (exlen > 10) {
minID = history.messages[exlen - 1].id;
minID = history.messages[exlen - 1].mid;
$scope.historyState.skipped = hasLess = minID > 0;
if (hasLess) {
loadAfterSync = peerID;
@ -1825,7 +1825,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -1825,7 +1825,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
i;
for (i = 0; i < history.messages.length; i++) {
if (!historyUpdate.msgs[history.messages[i].id]) {
if (!historyUpdate.msgs[history.messages[i].mid]) {
newMessages.push(history.messages[i]);
}
};
@ -1949,7 +1949,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -1949,7 +1949,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
var timeout = 0;
var options = {
replyToMsgID: $scope.draftMessage.replyToMessage && $scope.draftMessage.replyToMessage.id
replyToMsgID: $scope.draftMessage.replyToMessage && $scope.draftMessage.replyToMessage.mid
};
do {
@ -2074,7 +2074,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -2074,7 +2074,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
var message = $scope.draftMessage.replyToMessage;
if (message &&
$scope.historyState.replyKeyboard &&
$scope.historyState.replyKeyboard.id == message.id &&
$scope.historyState.replyKeyboard.mid == message.mid &&
!$scope.historyState.replyKeyboard.pFlags.hidden) {
$scope.historyState.replyKeyboard.pFlags.hidden = true;
$scope.$broadcast('ui_keyboard_update');
@ -2110,7 +2110,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -2110,7 +2110,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
(replyKeyboard._ == 'replyKeyboardMarkup' && peerID < 0));
if (addReplyMessage) {
replySelect(replyKeyboard.id);
replySelect(replyKeyboard.mid);
replyToMarkup = true;
}
else if (replyToMarkup) {
@ -2162,7 +2162,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -2162,7 +2162,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
return;
}
var options = {
replyToMsgID: $scope.draftMessage.replyToMessage && $scope.draftMessage.replyToMessage.id,
replyToMsgID: $scope.draftMessage.replyToMessage && $scope.draftMessage.replyToMessage.mid,
isMedia: $scope.draftMessage.isMedia
};
@ -2196,7 +2196,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -2196,7 +2196,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
}
}
var options = {
replyToMsgID: $scope.draftMessage.replyToMessage && $scope.draftMessage.replyToMessage.id
replyToMsgID: $scope.draftMessage.replyToMessage && $scope.draftMessage.replyToMessage.mid
};
AppMessagesManager.sendOther($scope.curDialog.peerID, inputMedia, options);
$scope.$broadcast('ui_message_send');
@ -2647,15 +2647,18 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -2647,15 +2647,18 @@ angular.module('myApp.controllers', ['myApp.i18n'])
})
.controller('ChatpicModalController', function ($q, $scope, $rootScope, $modalInstance, MtpApiManager, AppPhotosManager, AppChatsManager, AppPeersManager, AppMessagesManager, PeersSelectService, ErrorService) {
.controller('ChatpicModalController', function ($q, $scope, $rootScope, $modalInstance, MtpApiManager, AppPhotosManager, AppChatsManager, AppPeersManager, AppMessagesManager, ApiUpdatesManager, PeersSelectService, ErrorService) {
$scope.photo = AppPhotosManager.wrapForFull($scope.photoID);
$scope.photo.thumb = {
location: AppPhotosManager.choosePhotoSize($scope.photo, 0, 0).location
};
var chat = AppChatsManager.getChat($scope.chatID);
var isChannel = AppChatsManager.isChannel($scope.chatID);
$scope.canForward = true;
$scope.canDelete = true;
$scope.canDelete = isChannel ? chat.pFlags.creator : true;
$scope.forward = function () {
PeersSelectService.selectPeers({confirm_type: 'FORWARD_PEER'}).then(function (peerStrings) {
@ -2679,10 +2682,19 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -2679,10 +2682,19 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope['delete'] = function () {
ErrorService.confirm({type: 'PHOTO_DELETE'}).then(function () {
$scope.photo.updating = true;
MtpApiManager.invokeApi('messages.editChatPhoto', {
chat_id: AppChatsManager.getChatInput($scope.chatID),
photo: {_: 'inputChatPhotoEmpty'}
}).then(function (updates) {
var apiPromise;
if (AppChatsManager.isChannel($scope.chatID)) {
apiPromise = MtpApiManager.invokeApi('channels.editPhoto', {
channel: AppChatsManager.getChannelInput($scope.chatID),
photo: {_: 'inputChatPhotoEmpty'}
});
} else {
apiPromise = MtpApiManager.invokeApi('messages.editChatPhoto', {
chat_id: AppChatsManager.getChatInput($scope.chatID),
photo: {_: 'inputChatPhotoEmpty'}
});
}
apiPromise.then(function (updates) {
ApiUpdatesManager.processUpdateMessage(updates);
$modalInstance.dismiss();
$rootScope.$broadcast('history_focus', {peerString: AppChatsManager.getChatString($scope.chatID)});
@ -3069,6 +3081,150 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -3069,6 +3081,150 @@ angular.module('myApp.controllers', ['myApp.i18n'])
})
.controller('ChannelModalController', function ($scope, $timeout, $rootScope, $modal, AppUsersManager, AppChatsManager, AppPhotosManager, MtpApiManager, MtpApiFileManager, NotificationsManager, AppMessagesManager, AppPeersManager, ApiUpdatesManager, ContactsSelectService, ErrorService) {
$scope.chatFull = AppChatsManager.wrapForFull($scope.chatID, {});
$scope.settings = {notifications: true};
AppChatsManager.getChannelFull($scope.chatID, true).then(function (chatFull) {
$scope.chatFull = AppChatsManager.wrapForFull($scope.chatID, chatFull);
$scope.$broadcast('ui_height');
NotificationsManager.savePeerSettings(-$scope.chatID, chatFull.notify_settings);
NotificationsManager.getPeerMuted(-$scope.chatID).then(function (muted) {
$scope.settings.notifications = !muted;
$scope.$watch('settings.notifications', function(newValue, oldValue) {
if (newValue === oldValue) {
return false;
}
NotificationsManager.getPeerSettings(-$scope.chatID).then(function (settings) {
if (newValue) {
settings.mute_until = 0;
} else {
settings.mute_until = 2000000000;
}
NotificationsManager.updatePeerSettings(-$scope.chatID, settings);
});
});
});
});
function onChatUpdated (updates) {
ApiUpdatesManager.processUpdateMessage(updates);
$rootScope.$broadcast('history_focus', {peerString: $scope.chatFull.peerString});
}
$scope.leaveChannel = function () {
MtpApiManager.invokeApi('channels.leaveChannel', {
channel: AppChatsManager.getChannelInput($scope.chatID)
}).then(onChatUpdated);
};
$scope.deleteChannel = function () {
return ErrorService.confirm({type: 'CHANNEL_DELETE'}).then(function () {
MtpApiManager.invokeApi('channels.deleteChannel', {
channel: AppChatsManager.getChannelInput($scope.chatID)
}).then(onChatUpdated);
});
}
$scope.joinChannel = function () {
MtpApiManager.invokeApi('channels.joinChannel', {
channel: AppChatsManager.getChannelInput($scope.chatID)
}).then(onChatUpdated);
};
$scope.inviteToChannel = function () {
var disabled = [];
angular.forEach(($scope.chatFull.participants || {}).participants || [], function(participant){
disabled.push(participant.user_id);
});
ContactsSelectService.selectContacts({disabled: disabled}).then(function (userIDs) {
var inputUsers = [];
angular.forEach(userIDs, function (userID) {
inputUsers.push(AppUsersManager.getUserInput(userID));
});
MtpApiManager.invokeApi('channels.inviteToChannel', {
channel: AppChatsManager.getChannelInput($scope.chatID),
users: inputUsers
}).then(onChatUpdated);
});
};
$scope.kickFromChannel = function (userID) {
MtpApiManager.invokeApi('channels.kickFromChannel', {
channel: AppChatsManager.getChannelInput($scope.chatID),
user_id: AppUsersManager.getUserInput(userID),
kicked: true
}).then(onChatUpdated);
};
$scope.shareLink = function ($event) {
var scope = $rootScope.$new();
scope.chatID = $scope.chatID;
$modal.open({
templateUrl: templateUrl('chat_invite_link_modal'),
controller: 'ChatInviteLinkModalController',
scope: scope,
windowClass: 'md_simple_modal_window'
});
return cancelEvent($event);
}
$scope.photo = {};
$scope.$watch('photo.file', onPhotoSelected);
function onPhotoSelected (photo) {
if (!photo || !photo.type || photo.type.indexOf('image') !== 0) {
return;
}
$scope.photo.updating = true;
MtpApiFileManager.uploadFile(photo).then(function (inputFile) {
return MtpApiManager.invokeApi('channels.editPhoto', {
channel: AppChatsManager.getChannelInput($scope.chatID),
photo: {
_: 'inputChatUploadedPhoto',
file: inputFile,
crop: {_: 'inputPhotoCropAuto'}
}
}).then(onChatUpdated);
})['finally'](function () {
$scope.photo.updating = false;
});
};
$scope.deletePhoto = function () {
$scope.photo.updating = true;
MtpApiManager.invokeApi('messages.editChatPhoto', {
channel: AppChatsManager.getChannelInput($scope.chatID),
photo: {_: 'inputChatPhotoEmpty'}
}).then(onChatUpdated)['finally'](function () {
$scope.photo.updating = false;
});
};
$scope.editChannel = function () {
var scope = $rootScope.$new();
scope.chatID = $scope.chatID;
$modal.open({
templateUrl: templateUrl('channel_edit_modal'),
controller: 'ChannelEditModalController',
scope: scope,
windowClass: 'md_simple_modal_window mobile_modal'
});
}
})
.controller('SettingsModalController', function ($rootScope, $scope, $timeout, $modal, AppUsersManager, AppChatsManager, AppPhotosManager, MtpApiManager, Storage, NotificationsManager, MtpApiFileManager, PasswordManager, ApiUpdatesManager, ChangelogNotifyService, LayoutSwitchService, AppRuntimeManager, ErrorService, _) {
$scope.profile = {};
@ -3911,12 +4067,21 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -3911,12 +4067,21 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.group.updating = true;
return MtpApiManager.invokeApi('messages.editChatTitle', {
chat_id: AppChatsManager.getChatInput($scope.chatID),
title: $scope.group.name
}).then(function (updates) {
ApiUpdatesManager.processUpdateMessage(updates);
var apiPromise;
if (AppChatsManager.isChannel($scope.chatID)) {
apiPromise = MtpApiManager.invokeApi('channels.editTitle', {
channel: AppChatsManager.getChannelInput($scope.chatID),
title: $scope.group.name
});
} else {
apiPromise = MtpApiManager.invokeApi('messages.editChatTitle', {
chat_id: AppChatsManager.getChatInput($scope.chatID),
title: $scope.group.name
});
}
return apiPromise.then(function (updates) {
ApiUpdatesManager.processUpdateMessage(updates);
var peerString = AppChatsManager.getChatString($scope.chatID);
$rootScope.$broadcast('history_focus', {peerString: peerString});
})['finally'](function () {
@ -3925,19 +4090,80 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -3925,19 +4090,80 @@ angular.module('myApp.controllers', ['myApp.i18n'])
};
})
.controller('ChannelEditModalController', function ($q, $scope, $modalInstance, $rootScope, MtpApiManager, AppUsersManager, AppChatsManager, ApiUpdatesManager) {
var channel = AppChatsManager.getChat($scope.chatID);
var initial = {title: channel.title};
$scope.channel = {title: channel.title};
AppChatsManager.getChannelFull($scope.chatID).then(function (channelFull) {
initial.about = channelFull.about;
$scope.channel.about = channelFull.about;
});
$scope.updateChannel = function () {
if (!$scope.channel.title.length) {
return;
}
var promises = [];
if ($scope.channel.title != initial.title) {
promises.push(editTitle());
}
if ($scope.channel.about != initial.about) {
promises.push(editAbout());
}
return $q.all(promises).then(function () {
var peerString = AppChatsManager.getChatString($scope.chatID);
$rootScope.$broadcast('history_focus', {peerString: peerString});
})['finally'](function () {
delete $scope.channel.updating;
});
};
function editTitle () {
return MtpApiManager.invokeApi('channels.editTitle', {
channel: AppChatsManager.getChannelInput($scope.chatID),
title: $scope.channel.title
}).then(function (updates) {
ApiUpdatesManager.processUpdateMessage(updates);
});
}
function editAbout () {
return MtpApiManager.invokeApi('channels.editAbout', {
channel: AppChatsManager.getChannelInput($scope.chatID),
about: $scope.channel.about
});
}
})
.controller('ChatInviteLinkModalController', function (_, $scope, $timeout, $modalInstance, AppChatsManager, ErrorService) {
$scope.exportedInvite = {link: _('group_invite_link_loading_raw')};
var isChannel = AppChatsManager.isChannel($scope.chatID);
function selectLink () {
$timeout(function () {
$scope.$broadcast('ui_invite_select');
}, 100);
}
function updateLink (force) {
var chat = AppChatsManager.getChat($scope.chatID);
if (chat.username) {
$scope.exportedInvite = {link: 'https://telegram.me/' + chat.username, short: true};
selectLink();
return;
}
if (force) {
$scope.exportedInvite.revoking = true;
}
AppChatsManager.getChatInviteLink($scope.chatID, force).then(function (link) {
$scope.exportedInvite = {link: link};
$timeout(function () {
$scope.$broadcast('ui_invite_select');
}, 100);
$scope.exportedInvite = {link: link, canRevoke: true};
selectLink();
})['finally'](function () {
delete $scope.exportedInvite.revoking;
});
@ -3945,7 +4171,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -3945,7 +4171,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.revokeLink = function () {
ErrorService.confirm({
type: 'REVOKE_GROUP_INVITE_LINK'
type: isChannel ? 'REVOKE_CHANNEL_INVITE_LINK' : 'REVOKE_GROUP_INVITE_LINK'
}).then(function () {
updateLink(true);
})

30
app/js/directives.js

@ -65,7 +65,7 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -65,7 +65,7 @@ angular.module('myApp.directives', ['myApp.filters'])
needDate = false,
unreadAfter = false,
applySelected = function () {
if (selected != ($scope.selectedMsgs[$scope.historyMessage.id] || false)) {
if (selected != ($scope.selectedMsgs[$scope.historyMessage.mid] || false)) {
selected = !selected;
element.toggleClass(selectedClass, selected);
}
@ -109,7 +109,7 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -109,7 +109,7 @@ angular.module('myApp.directives', ['myApp.filters'])
$scope.$on('messages_regroup', applyGrouped);
$scope.$on('messages_focus', function (e, focusedMsgID) {
if ((focusedMsgID == $scope.historyMessage.id) != focused) {
if ((focusedMsgID == $scope.historyMessage.mid) != focused) {
focused = !focused;
element.toggleClass(focusClass, focused);
}
@ -122,7 +122,7 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -122,7 +122,7 @@ angular.module('myApp.directives', ['myApp.filters'])
if ($scope.peerHistory.peerID != $scope.historyPeer.id) {
return;
}
if (unreadAfter != ($scope.historyUnreadAfter == $scope.historyMessage.id)) {
if (unreadAfter != ($scope.historyUnreadAfter == $scope.historyMessage.mid)) {
unreadAfter = !unreadAfter;
if (unreadAfter) {
if (unreadAfterSplit) {
@ -362,10 +362,10 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -362,10 +362,10 @@ angular.module('myApp.directives', ['myApp.filters'])
if (!message.loading) {
updateMessage($scope, element);
} else {
var messageID = message.id;
var stopWaiting = $scope.$on('messages_downloaded', function (e, msgIDs) {
if (msgIDs.indexOf(messageID) != -1) {
$scope.replyMessage = AppMessagesManager.wrapForDialog(messageID);
var mid = message.mid;
var stopWaiting = $scope.$on('messages_downloaded', function (e, mids) {
if (mids.indexOf(mid) != -1) {
$scope.replyMessage = AppMessagesManager.wrapForDialog(mid);
updateMessage($scope, element);
stopWaiting();
}
@ -379,6 +379,7 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -379,6 +379,7 @@ angular.module('myApp.directives', ['myApp.filters'])
$(element).remove();
return;
}
console.log(element[0], message, AppPeersManager.getPeer(message.fromID));
var thumbWidth = 42;
var thumbHeight = 42;
var thumbPhotoSize;
@ -421,10 +422,14 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -421,10 +422,14 @@ angular.module('myApp.directives', ['myApp.filters'])
var peerID = AppMessagesManager.getMessagePeer(message);
var peerString = AppPeersManager.getPeerString(peerID);
$rootScope.$broadcast('history_focus', {peerString: peerString, messageID: message.id});
$rootScope.$broadcast('history_focus', {peerString: peerString, messageID: message.mid});
})
}
onContentLoaded(function () {
$scope.$emit('ui_height');
})
}
})
@ -465,7 +470,7 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -465,7 +470,7 @@ angular.module('myApp.directives', ['myApp.filters'])
function link ($scope, element, attrs) {
var message = $scope.message;
var msgID = message.id;
var msgID = message.mid;
// var msgID = $scope.$eval(attrs.myMessageText);
// var message = AppMessagesManager.getMessage(msgID);
@ -473,7 +478,7 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -473,7 +478,7 @@ angular.module('myApp.directives', ['myApp.filters'])
if (message.pending) {
var unlink = $scope.$on('messages_pending', function () {
if (message.id != msgID) {
if (message.mid != msgID) {
updateHtml(message, element);
unlink();
}
@ -2546,6 +2551,9 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -2546,6 +2551,9 @@ angular.module('myApp.directives', ['myApp.filters'])
return;
}
AppChatsManager.getChatFull(chatID).then(function (chatFull) {
if (chatFull.participants_count) {
participantsCount = chatFull.participants_count;
}
var participantsVector = (chatFull.participants || {}).participants || [];
participantsCount = participantsVector.length;
angular.forEach(participantsVector, function (participant) {
@ -2920,7 +2928,7 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -2920,7 +2928,7 @@ angular.module('myApp.directives', ['myApp.filters'])
if ($scope.message &&
!$scope.message.out &&
$scope.message.media_unread) {
AppMessagesManager.readMessages([$scope.message.id]);
AppMessagesManager.readMessages([$scope.message.mid]);
}
}, 300);
});

17
app/js/locales/en-us.json

@ -27,6 +27,14 @@ @@ -27,6 +27,14 @@
"group_modal_members": "Members",
"group_modal_members_kick": "Remove",
"channel_modal_info": "Channel info",
"channel_modal_share_link": "Share link",
"channel_modal_share_loading": "Loading{dots}",
"channel_modal_join": "Join channel",
"channel_modal_add_member": "Invite members",
"channel_modal_leave_channel": "Leave channel",
"channel_modal_delete_channel": "Delete channel",
"country_select_modal_title": "Country",
"settings_modal_title": "Settings",
@ -173,6 +181,12 @@ @@ -173,6 +181,12 @@
"group_edit_submit": "Save",
"group_edit_submit_active": "Saving...",
"channel_edit_modal_title": "Edit channel",
"channel_edit_name": "Channel name",
"channel_edit_about": "Channel description",
"channel_edit_submit": "Save",
"channel_edit_submit_active": "Saving...",
"group_invite_link_modal_title": "Invite link",
"group_invite_link_link_label": "Copy link",
"group_invite_link_loading": "Loading...",
@ -204,6 +218,9 @@ @@ -204,6 +218,9 @@
"confirm_modal_reset_account_md": "Are you sure?\nThis action can not be undone.\n\nYou will lose all your chats and messages, along with any media and files you shared, if you proceed with resetting your account.",
"confirm_modal_join_group_link": "Do you want to join the group «{title}»?",
"confirm_modal_revoke_group_link": "Are you sure you want to revoke this link? Once you do, no one will be able to join the group using it.",
"confirm_modal_revoke_channel_link": "Are you sure you want to revoke this link? Once you do, no one will be able to join the channel using it.",
"confirm_modal_delete_channel_md": "Are you sure you want to delete this channel?\n\nAll messages will be removed and all messages will be lost.",
"confirm_modal_are_u_sure": "Are you sure?",
"confirm_modal_logout_submit": "Log out",

391
app/js/services.js

@ -113,8 +113,6 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -113,8 +113,6 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
usernames[searchUsername] = userID;
}
apiUser.sortName = SearchIndexManager.cleanSearchText(apiUser.first_name + ' ' + (apiUser.last_name || ''));
apiUser.pFlags = {
self: (apiUser.flags & (1 << 10)) > 0,
contact: (apiUser.flags & (1 << 11)) > 0,
@ -125,6 +123,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -125,6 +123,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
botNoGroups: (apiUser.flags & (1 << 16)) > 0
};
apiUser.sortName = apiUser.pFlags.deleted ? '' : SearchIndexManager.cleanSearchText(apiUser.first_name + ' ' + (apiUser.last_name || ''));
var nameWords = apiUser.sortName.split(' ');
var firstWord = nameWords.shift();
var lastWord = nameWords.pop();
@ -553,6 +553,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -553,6 +553,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
usernames = {},
chatsFull = {},
chatFullPromises = {},
channelAccess = {},
cachedPhotoLocations = {};
function saveApiChats (apiChats) {
@ -565,6 +566,23 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -565,6 +566,23 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}
apiChat.rTitle = RichTextProcessor.wrapRichText(apiChat.title, {noLinks: true, noLinebreaks: true}) || _('chat_title_deleted');
var flags = apiChat.flags;
apiChat.pFlags = {
creator: (flags & (1 << 0)) > 0,
kicked: (flags & (1 << 1)) > 0,
left: (flags & (1 << 2)) > 0
};
if (apiChat._ == 'channel') {
angular.extend(apiChat.pFlags, {
editor: (apiChat.flags & (1 << 3)) > 0,
moderator: (apiChat.flags & (1 << 4)) > 0,
broadcast: (apiChat.flags & (1 << 5)) > 0,
username: (apiChat.flags & (1 << 6)) > 0,
verified: (apiChat.flags & (1 << 7)) > 0
});
};
var titleWords = SearchIndexManager.cleanSearchText(apiChat.title || '').split(' ');
var firstWord = titleWords.shift();
var lastWord = titleWords.pop();
@ -597,8 +615,17 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -597,8 +615,17 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
return usernames[username] || 0;
}
function saveChannelAccess (id, accessHash) {
channelAccess[id] = accessHash;
}
function isChannel (id) {
return (chats[id] || {})._ == 'channel';
var chat = chats[id];
if (chat && chat._ == 'channel' ||
channelAccess[id]) {
return true;
}
return false;
}
function getChatInput (id) {
@ -612,11 +639,14 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -612,11 +639,14 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
return {
_: 'inputChannel',
channel_id: id,
access_hash: getChat(id).access_hash || 0
access_hash: getChat(id).access_hash || channelAccess[id] || 0
}
}
function getChatFull(id) {
if (isChannel(id)) {
return getChannelFull(id);
}
if (chatsFull[id] !== undefined) {
if (chats[id].version == chatsFull[id].participants.version ||
chats[id].left) {
@ -631,13 +661,72 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -631,13 +661,72 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}).then(function (result) {
saveApiChats(result.chats);
AppUsersManager.saveApiUsers(result.users);
if (result.full_chat && result.full_chat.chat_photo.id) {
AppPhotosManager.savePhoto(result.full_chat.chat_photo);
var fullChat = result.full_chat;
if (fullChat && fullChat.chat_photo.id) {
AppPhotosManager.savePhoto(fullChat.chat_photo);
}
delete chatFullPromises[id];
chatsFull[id] = fullChat;
$rootScope.$broadcast('chat_full_update', id);
return chatsFull[id] = result.full_chat;
return fullChat;
});
}
function getChannelFull (id, force) {
if (chatsFull[id] !== undefined && !force) {
return $q.when(chatsFull[id]);
}
if (chatFullPromises[id] !== undefined) {
return chatFullPromises[id];
}
return chatFullPromises[id] = MtpApiManager.invokeApi('channels.getFullChannel', {
channel: getChannelInput(id)
}).then(function (result) {
saveApiChats(result.chats);
AppUsersManager.saveApiUsers(result.users);
var fullChannel = result.full_chat;
var chat = getChat(id);
if (fullChannel && fullChannel.chat_photo.id) {
AppPhotosManager.savePhoto(fullChannel.chat_photo);
}
var participantsPromise;
if ((fullChannel.flags & 8) ||
chat.pFlags.creator ||
chat.pFlags.editor ||
chat.pFlags.moderator) {
participantsPromise = getChannelParticipants(id).then(function (participants) {
delete chatFullPromises[id];
fullChannel.participants = {
_: 'channelParticipants',
participants: participants
};
}, function (error) {
error.handled = true;
});
} else {
participantsPromise = $q.when();
}
return participantsPromise.then(function () {
delete chatFullPromises[id];
chatsFull[id] = fullChannel;
$rootScope.$broadcast('chat_full_update', id);
return fullChannel;
});
});
}
function getChannelParticipants (id) {
return MtpApiManager.invokeApi('channels.getParticipants', {
channel: getChannelInput(id),
filter: {_: 'channelParticipantsRecent'},
offset: 0,
limit: 200
}).then(function (result) {
AppUsersManager.saveApiUsers(result.users);
return result.participants;
});
}
@ -688,25 +777,33 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -688,25 +777,33 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
var chatFull = angular.copy(fullChat),
chat = getChat(id);
if (chatFull.participants && chatFull.participants._ == 'chatParticipants') {
MtpApiManager.getUserID().then(function (myID) {
chatFull.isAdmin = (myID == chatFull.participants.admin_id);
angular.forEach(chatFull.participants.participants, function(participant){
participant.user = AppUsersManager.getUser(participant.user_id);
participant.canLeave = myID == participant.user_id;
participant.canKick = !participant.canLeave && (chatFull.isAdmin || myID == participant.inviter_id);
// just for order by last seen
participant.user = AppUsersManager.getUser(participant.user_id);
});
});
}
if (chatFull.participants && chatFull.participants._ == 'channelParticipants') {
var isAdmin = chat.pFlags.creator || chat.pFlags.editor || chat.pFlags.moderator;
angular.forEach(chatFull.participants.participants, function(participant) {
participant.canLeave = !chat.pFlags.creator && participant._ == 'channelParticipantSelf';
participant.canKick = isAdmin && participant._ == 'channelParticipant';
// just for order by last seen
participant.user = AppUsersManager.getUser(participant.user_id);
});
}
if (chatFull.about) {
chatFull.rAbout = RichTextProcessor.wrapRichText(chatFull.about, {noLinebreaks: true});
}
chatFull.thumb = {
placeholder: 'img/placeholders/GroupAvatar'+(Config.Mobile ? chat.num : Math.ceil(chat.num / 2))+'@2x.png',
location: chat && chat.photo && chat.photo.photo_small,
width: 72,
height: 72,
size: 0
};
chatFull.peerString = getChatString(id);
chatFull.chat = chat;
@ -717,12 +814,21 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -717,12 +814,21 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
var scope = $rootScope.$new();
scope.chatID = chatID;
var modalInstance = $modal.open({
templateUrl: templateUrl('chat_modal'),
controller: 'ChatModalController',
scope: scope,
windowClass: 'chat_modal_window mobile_modal'
});
if (isChannel(chatID)) {
var modalInstance = $modal.open({
templateUrl: templateUrl('channel_modal'),
controller: 'ChannelModalController',
scope: scope,
windowClass: 'chat_modal_window channel_modal_window mobile_modal'
});
} else {
var modalInstance = $modal.open({
templateUrl: templateUrl('chat_modal'),
controller: 'ChatModalController',
scope: scope,
windowClass: 'chat_modal_window mobile_modal'
});
}
}
$rootScope.$on('apiUpdate', function (e, update) {
@ -779,9 +885,11 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -779,9 +885,11 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
saveApiChat: saveApiChat,
getChat: getChat,
isChannel: isChannel,
saveChannelAccess: saveChannelAccess,
getChatInput: getChatInput,
getChannelInput: getChannelInput,
getChatFull: getChatFull,
getChannelFull: getChannelFull,
getChatPhoto: getChatPhoto,
getChatString: getChatString,
getChatInviteLink: getChatInviteLink,
@ -806,6 +914,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -806,6 +914,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
};
}
else if (firstChar == 'c') {
AppChatsManager.saveChannelAccess(peerParams[0], peerParams[1]);
return {
_: 'inputPeerChannel',
channel_id: peerParams[0],
@ -875,13 +984,13 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -875,13 +984,13 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
function resolveUsername (username) {
var searchUserName = SearchIndexManager.cleanUsername(username);
var foundUserID, foundChatID, foundPeerID, foundUsername;
if (foundUserID == AppUsersManager.resolveUsername(searchUserName)) {
if (foundUserID = AppUsersManager.resolveUsername(searchUserName)) {
foundUsername = AppUsersManager.getUser(foundUserID).username;
if (SearchIndexManager.cleanUsername(foundUsername) == searchUserName) {
return qSync.when(foundUserID);
}
}
if (foundChatID == AppChatsManager.resolveUsername(searchUserName)) {
if (foundChatID = AppChatsManager.resolveUsername(searchUserName)) {
foundUsername = AppChatsManager.getChat(foundChatID).username;
if (SearchIndexManager.cleanUsername(foundUsername) == searchUserName) {
return qSync.when(-foundChatID);
@ -1171,8 +1280,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -1171,8 +1280,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
var peerText = AppPeersManager.getPeerSearchText(peerID);
SearchIndexManager.indexObject(peerID, peerText, dialogsIndex);
var messageID = dialog.top_important_message;
dialog.top_message = peerID + '_' + messageID;
var mid = getFullMessageID(dialog.top_important_message, -peerID);
dialog.top_message = mid;
var message = getMessage(dialog.top_message);
var topDate = message.date;
@ -1187,7 +1296,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -1187,7 +1296,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
pushDialogToStorage(dialog);
if (historiesStorage[peerID] === undefined) {
var historyStorage = {count: null, history: [messageID], pending: []};
var historyStorage = {count: null, history: [mid], pending: []};
historiesStorage[peerID] = historyStorage;
}
@ -1305,15 +1414,15 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -1305,15 +1414,15 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
var promise;
if (AppPeersManager.isChannel(peerID)) {
promise = MtpApiManager.invokeApi('channels.getImportantHistory', {
peer: inputPeer,
offset_id: maxID || 0,
channel: AppChatsManager.getChannelInput(-peerID),
offset_id: maxID ? getMessageLocalID(maxID) : 0,
add_offset: offset || 0,
limit: limit || 0
}, {noErrorBox: true});
} else {
promise = MtpApiManager.invokeApi('messages.getHistory', {
peer: inputPeer,
offset_id: maxID || 0,
offset_id: maxID ? getMessageLocalID(maxID) : 0,
add_offset: offset || 0,
limit: limit || 0
}, {noErrorBox: true});
@ -1359,6 +1468,40 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -1359,6 +1468,40 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
});
}
var channelLocals = {};
var channelsByLocals = {};
var channelCurLocal = 0;
var fullMsgIDModulus = 4294967296;
function getFullMessageID (msgID, channelID) {
if (!channelID) {
return msgID;
}
msgID = getMessageLocalID(msgID);
var localStart = channelLocals[channelID];
if (!localStart) {
localStart = (++channelCurLocal) * fullMsgIDModulus;
channelsByLocals[localStart] = channelID;
channelLocals[channelID] = localStart;
}
return localStart + msgID;
}
function getMessageIDInfo (fullMsgID) {
if (fullMsgID < fullMsgIDModulus) {
return [fullMsgID, 0];
}
var msgID = fullMsgID % fullMsgIDModulus;
var channelID = channelsByLocals[fullMsgID - msgID];
return [msgID, channelID];
}
function getMessageLocalID (fullMsgID) {
return fullMsgID % fullMsgIDModulus;
}
function fillHistoryStorage (inputPeer, maxID, fullLimit, historyStorage) {
// console.log('fill history storage', inputPeer, maxID, fullLimit, angular.copy(historyStorage));
return requestHistory (inputPeer, maxID, fullLimit).then(function (historyResult) {
@ -1366,7 +1509,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -1366,7 +1509,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
var offset = 0;
if (!maxID && historyResult.messages.length) {
maxID = historyResult.messages[0].id + 1;
maxID = historyResult.messages[0].mid + 1;
}
if (maxID > 0) {
for (offset = 0; offset < historyStorage.history.length; offset++) {
@ -1381,7 +1524,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -1381,7 +1524,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
if (mergeReplyKeyboard(historyStorage, message)) {
$rootScope.$broadcast('history_reply_markup', {peerID: AppPeersManager.getPeerID(inputPeer)});
}
historyStorage.history.push(message.id);
historyStorage.history.push(message.mid);
});
fullLimit -= historyResult.messages.length;
@ -1479,7 +1622,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -1479,7 +1622,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
var history = [];
angular.forEach(historyResult.messages, function (message) {
history.push(message.id);
history.push(message.mid);
});
if (!maxID && historyStorage.pending.length) {
history = historyStorage.pending.slice().concat(history);
@ -1523,7 +1666,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -1523,7 +1666,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}
function mergeReplyKeyboard (historyStorage, message) {
// console.log('merge', message.id, message.reply_markup, historyStorage.reply_markup);
// console.log('merge', message.mid, message.reply_markup, historyStorage.reply_markup);
if (!message.reply_markup &&
!message.out &&
!message.action) {
@ -1532,7 +1675,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -1532,7 +1675,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
var messageReplyMarkup = message.reply_markup;
var lastReplyMarkup = historyStorage.reply_markup;
if (messageReplyMarkup) {
if (lastReplyMarkup && lastReplyMarkup.id >= message.id) {
if (lastReplyMarkup && lastReplyMarkup.mid >= message.mid) {
return false;
}
if (messageReplyMarkup.pFlags.selective &&
@ -1540,12 +1683,12 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -1540,12 +1683,12 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
return false;
}
if (historyStorage.maxOutID &&
message.id < historyStorage.maxOutID &&
message.mid < historyStorage.maxOutID &&
messageReplyMarkup.pFlags.one_time) {
messageReplyMarkup.pFlags.hidden = true;
}
messageReplyMarkup = angular.extend({
id: message.id
id: message.mid
}, messageReplyMarkup);
if (messageReplyMarkup._ != 'replyKeyboardHide') {
messageReplyMarkup.fromID = message.from_id;
@ -1559,15 +1702,15 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -1559,15 +1702,15 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
if (lastReplyMarkup) {
if (lastReplyMarkup.pFlags.one_time &&
!lastReplyMarkup.pFlags.hidden &&
(message.id > lastReplyMarkup.id || message.id < 0) &&
(message.mid > lastReplyMarkup.mid || message.mid < 0) &&
message.message) {
lastReplyMarkup.pFlags.hidden = true;
// console.log('set', historyStorage.reply_markup);
return true;
}
} else if (!historyStorage.maxOutID ||
message.id > historyStorage.maxOutID) {
historyStorage.maxOutID = message.id;
message.mid > historyStorage.maxOutID) {
historyStorage.maxOutID = message.mid;
}
}
@ -1580,7 +1723,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -1580,7 +1723,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
) {
historyStorage.reply_markup = {
_: 'replyKeyboardHide',
id: message.id,
mid: message.mid,
flags: 0,
pFlags: {}
};
@ -1636,7 +1779,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -1636,7 +1779,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
for (i = 0; i < historyStorage.history.length; i++) {
message = messagesStorage[historyStorage.history[i]];
if (message.media && neededContents[message.media._]) {
foundMsgs.push(message.id);
foundMsgs.push(message.mid);
if (foundMsgs.length >= neededLimit) {
break;
}
@ -1688,7 +1831,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -1688,7 +1831,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
foundMsgs = [];
angular.forEach(searchResult.messages, function (message) {
foundMsgs.push(message.id);
foundMsgs.push(message.mid);
});
if (useSearchCache) {
@ -1753,6 +1896,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -1753,6 +1896,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
function readHistory (inputPeer) {
// console.trace('start read');
var peerID = AppPeersManager.getPeerID(inputPeer),
isChannel = AppPeersManager.isChannel(peerID),
historyStorage = historiesStorage[peerID],
foundDialog = getDialogByPeerID(peerID);
@ -1783,13 +1927,23 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -1783,13 +1927,23 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
return historyStorage.readPromise;
}
historyStorage.readPromise = MtpApiManager.invokeApi('messages.readHistory', {
peer: inputPeer,
offset: 0,
max_id: 0
}).then(function (affectedHistory) {
return processAffectedHistory(inputPeer, affectedHistory, 'messages.readHistory');
}).then(function () {
var apiPromise;
if (isChannel) {
apiPromise = MtpApiManager.invokeApi('channels.readHistory', {
channel: AppChatsManager.getChannelInput(-peerID),
max_id: 0
});
} else {
apiPromise = MtpApiManager.invokeApi('messages.readHistory', {
peer: inputPeer,
offset: 0,
max_id: 0
}).then(function (affectedHistory) {
return processAffectedHistory(inputPeer, affectedHistory, 'messages.readHistory');
});
}
historyStorage.readPromise = apiPromise.then(function () {
if (foundDialog[0]) {
// console.log('done read history', peerID);
foundDialog[0].unread_count = 0;
@ -1861,17 +2015,25 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -1861,17 +2015,25 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
function saveMessages (apiMessages) {
angular.forEach(apiMessages, function (apiMessage) {
if (apiMessage._ == 'messageEmpty') {
return;
}
apiMessage.unread = apiMessage.flags & 1 ? true : false;
apiMessage.out = apiMessage.flags & 2 ? true : false;
apiMessage.media_unread = apiMessage.flags & 32 ? true : false;
var toPeerID = AppPeersManager.getPeerID(apiMessage.to_id);
var isChannel = apiMessage.to_id._ == 'peerChannel';
var mid = isChannel ? toPeerID + '_' + apiMessage.id : apiMessage.id;
apiMessage.mid = mid;
var channelID = isChannel ? -toPeerID : 0;
var mid = getFullMessageID(apiMessage.id, channelID);
apiMessage.mid = mid;
messagesStorage[mid] = apiMessage;
if (apiMessage.reply_to_msg_id) {
apiMessage.reply_to_mid = getFullMessageID(apiMessage.reply_to_msg_id, channelID);
}
apiMessage.date -= serverTimeOffset;
apiMessage.toID = toPeerID;
apiMessage.fromID = apiMessage.from_id || toPeerID;
@ -1902,7 +2064,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -1902,7 +2064,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
AppAudioManager.saveAudio(apiMessage.media.audio);
break;
case 'messageMediaWebPage':
AppWebPagesManager.saveWebPage(apiMessage.media.webpage, apiMessage.id, mediaContext);
AppWebPagesManager.saveWebPage(apiMessage.media.webpage, apiMessage.mid, mediaContext);
break;
}
}
@ -1913,8 +2075,13 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -1913,8 +2075,13 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
apiMessage.action._ = 'messageActionChannelEditPhoto';
}
}
if (apiMessage.action._ == 'messageActionChatEditTitle' && isChannel) {
apiMessage.action._ = 'messageActionChannelEditTitle';
else if (isChannel) {
if (apiMessage.action._ == 'messageActionChatEditTitle') {
apiMessage.action._ = 'messageActionChannelEditTitle';
}
if (apiMessage.action._ == 'messageActionChatDeletePhoto') {
apiMessage.action._ = 'messageActionChannelDeletePhoto';
}
}
}
if (apiMessage.reply_markup) {
@ -2013,7 +2180,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -2013,7 +2180,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
peer: inputPeer,
message: text,
random_id: randomID,
reply_to_msg_id: replyToMsgID,
reply_to_msg_id: getMessageLocalID(replyToMsgID),
entities: entities
}, sentRequestOptions).then(function (updates) {
if (updates._ == 'updateShortSentMessage') {
@ -2187,7 +2354,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -2187,7 +2354,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
peer: inputPeer,
media: inputMedia,
random_id: randomID,
reply_to_msg_id: replyToMsgID
reply_to_msg_id: getMessageLocalID(replyToMsgID)
}).then(function (updates) {
ApiUpdatesManager.processUpdateMessage(updates);
}, function (error) {
@ -2319,7 +2486,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -2319,7 +2486,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
peer: inputPeer,
media: inputMedia,
random_id: randomID,
reply_to_msg_id: replyToMsgID
reply_to_msg_id: getMessageLocalID(replyToMsgID)
}).then(function (updates) {
ApiUpdatesManager.processUpdateMessage(updates);
}, function (error) {
@ -2337,20 +2504,26 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -2337,20 +2504,26 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
pendingByRandomID[randomIDS] = [peerID, messageID];
}
function forwardMessages (peerID, msgIDs) {
msgIDs = msgIDs.sort();
function forwardMessages (peerID, mids) {
mids = mids.sort();
var flags = 0;
var msgIDs = [];
var randomIDs = [];
var i;
var len = msgIDs.length;
for (var i = 0; i < msgIDs.length; i++) {
var len = mids.length;
var i, mid, msgID;
var fromChannel = getMessageIDInfo(mids[0])[1];
for (i = 0; i < len; i++) {
msgIDs.push(getMessageLocalID(mids[i]));
randomIDs.push([nextRandomInt(0xFFFFFFFF), nextRandomInt(0xFFFFFFFF)]);
}
return MtpApiManager.invokeApi('messages.forwardMessages', {
peer: AppPeersManager.getInputPeerByID(peerID),
flags: flags,
from_peer: AppPeersManager.getInputPeerByID(-fromChannel),
id: msgIDs,
random_id: randomIDs
random_id: randomIDs,
to_peer: AppPeersManager.getInputPeerByID(peerID),
}).then(function (updates) {
ApiUpdatesManager.processUpdateMessage(updates);
});
@ -2446,7 +2619,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -2446,7 +2619,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}
if (historyMessage = messagesForHistory[tempID]) {
messagesForHistory[finalMessage.id] = angular.extend(historyMessage, wrapForHistory(finalMessage.id));
messagesForHistory[finalMessage.mid] = angular.extend(historyMessage, wrapForHistory(finalMessage.mid));
delete historyMessage.pending;
delete historyMessage.error;
delete historyMessage.random_id;
@ -2654,12 +2827,12 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -2654,12 +2827,12 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}
}
var replyToMsgID = message.reply_to_msg_id;
var replyToMsgID = message.reply_to_mid;
if (replyToMsgID) {
if (messagesStorage[replyToMsgID] && false) {
if (messagesStorage[replyToMsgID]) {
message.reply_to_msg = wrapForDialog(replyToMsgID);
} else {
message.reply_to_msg = {id: replyToMsgID, loading: true};
message.reply_to_msg = {mid: replyToMsgID, loading: true};
if (needSingleMessages.indexOf(replyToMsgID) == -1) {
needSingleMessages.push(replyToMsgID);
if (fetchSingleMessagesTimeout === false) {
@ -2705,16 +2878,43 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -2705,16 +2878,43 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
if (!needSingleMessages.length) {
return;
}
var msgIDs = needSingleMessages.slice();
var mids = needSingleMessages.slice();
needSingleMessages = [];
MtpApiManager.invokeApi('messages.getMessages', {
id: msgIDs
}).then(function (getMessagesResult) {
AppUsersManager.saveApiUsers(getMessagesResult.users);
AppChatsManager.saveApiChats(getMessagesResult.chats);
saveMessages(getMessagesResult.messages);
$rootScope.$broadcast('messages_downloaded', msgIDs);
var msgIDsByChannels = {};
var midsByChannels = {};
var i, mid, msgChannel, channelID;
for (i = 0; i < mids.length; i++) {
mid = mids[i];
msgChannel = getMessageIDInfo(mid);
channelID = msgChannel[1];
if (msgIDsByChannels[channelID] === undefined) {
msgIDsByChannels[channelID] = [];
midsByChannels[channelID] = [];
}
msgIDsByChannels[channelID].push(msgChannel[0]);
midsByChannels[channelID].push(mid);
}
angular.forEach(msgIDsByChannels, function (msgIDs, channelID) {
var promise;
if (channelID > 0) {
promise = MtpApiManager.invokeApi('channels.getMessages', {
channel: AppChatsManager.getChannelInput(channelID),
id: msgIDs
});
} else {
promise = MtpApiManager.invokeApi('messages.getMessages', {
id: msgIDs
});
}
promise.then(function (getMessagesResult) {
AppUsersManager.saveApiUsers(getMessagesResult.users);
AppChatsManager.saveApiChats(getMessagesResult.chats);
saveMessages(getMessagesResult.messages);
$rootScope.$broadcast('messages_downloaded', midsByChannels[channelID]);
})
})
}
@ -2757,20 +2957,20 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -2757,20 +2957,20 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
if (curMessage.fwdFromID &&
curMessage.media &&
curMessage.media.document &&
curMessage.media.document.sticker &&
(curMessage.from_id != (prevMessage || {}).from_id || !(prevMessage || {}).fwdFromID)) {
(curMessage.media.document.sticker || curMessage.media.document.audioTitle) &&
(curMessage.fromID != (prevMessage || {}).fromID || !(prevMessage || {}).fwdFromID)) {
delete curMessage.fwdFromID;
curMessage._ = 'message';
}
if (prevMessage &&
curMessage.from_id == prevMessage.from_id &&
curMessage.fromID == prevMessage.fromID &&
!prevMessage.fwdFromID == !curMessage.fwdFromID &&
!prevMessage.action &&
!curMessage.action &&
curMessage.date < prevMessage.date + 900) {
var singleLine = curMessage.message && curMessage.message.length < 70 && curMessage.message.indexOf("\n") == -1 && !curMessage.reply_to_msg_id;
var singleLine = curMessage.message && curMessage.message.length < 70 && curMessage.message.indexOf("\n") == -1 && !curMessage.reply_to_mid;
if (groupFwd && curMessage.fwdFromID && curMessage.fwdFromID == prevMessage.fwdFromID) {
curMessage.grouped = singleLine ? 'im_grouped_fwd_short' : 'im_grouped_fwd';
} else {
@ -2922,13 +3122,13 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -2922,13 +3122,13 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
notification.onclick = function () {
$rootScope.$broadcast('history_focus', {
peerString: peerString,
messageID: message.flags & 16 ? message.id : 0,
messageID: message.flags & 16 ? message.mid : 0,
});
};
notification.message = notificationMessage;
notification.image = notificationPhoto.placeholder;
notification.key = 'msg' + message.id;
notification.key = 'msg' + message.mid;
notification.tag = peerString;
if (notificationPhoto.location && !notificationPhoto.location.empty) {
@ -3025,14 +3225,16 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -3025,14 +3225,16 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
peerID = getMessagePeer(message),
historyStorage = historiesStorage[peerID];
saveMessages([message]);
if (historyStorage !== undefined) {
var history = historyStorage.history;
if (history.indexOf(message.id) != -1) {
if (history.indexOf(message.mid) != -1) {
return false;
}
var topMsgID = history[0];
history.unshift(message.id);
if (message.id > 0 && message.id < topMsgID) {
history.unshift(message.mid);
if (message.mid > 0 && message.mid < topMsgID) {
history.sort(function (a, b) {
return b - a;
});
@ -3043,12 +3245,11 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -3043,12 +3245,11 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
} else {
historyStorage = historiesStorage[peerID] = {
count: null,
history: [message.id],
history: [message.mid],
pending: []
};
}
saveMessages([message]);
if (mergeReplyKeyboard(historyStorage, message)) {
$rootScope.$broadcast('history_reply_markup', {peerID: peerID})
@ -3058,21 +3259,21 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -3058,21 +3259,21 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
AppUsersManager.forceUserOnline(message.from_id);
}
var randomID = pendingByMessageID[message.id],
var randomID = pendingByMessageID[message.mid],
pendingMessage;
if (randomID) {
if (pendingMessage = finalizePendingMessage(randomID, message)) {
$rootScope.$broadcast('history_update', {peerID: peerID});
}
delete pendingByMessageID[message.id];
delete pendingByMessageID[message.mid];
}
if (!pendingMessage) {
if (newMessagesToHandle[peerID] === undefined) {
newMessagesToHandle[peerID] = [];
}
newMessagesToHandle[peerID].push(message.id);
newMessagesToHandle[peerID].push(message.mid);
if (!newMessagesHandlePromise) {
newMessagesHandlePromise = $timeout(handleNewMessages, 0);
}
@ -3088,7 +3289,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -3088,7 +3289,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
dialogsStorage.dialogs.splice(foundDialog[1], 1);
dialogsStorage.dialogs.unshift(dialog);
}
dialog.top_message = message.id;
dialog.top_message = message.mid;
if (inboxUnread) {
dialog.unread_count++;
}
@ -3098,7 +3299,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -3098,7 +3299,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
dialog = {
peerID: peerID,
unread_count: inboxUnread ? 1 : 0,
top_message: message.id
top_message: message.mid
};
dialogsStorage.dialogs.unshift(dialog);
}
@ -4586,7 +4787,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -4586,7 +4787,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
message: updateMessage.message,
fwd_from_id: updateMessage.fwd_from_id,
fwd_date: updateMessage.fwd_date,
reply_to_msg_id: updateMessage.reply_to_msg_id,
reply_to_msg_id: updateMessage.reply_to_msg_id
},
pts: updateMessage.pts,
pts_count: updateMessage.pts_count

15
app/less/app.less

@ -3652,7 +3652,7 @@ a.countries_modal_search_clear { @@ -3652,7 +3652,7 @@ a.countries_modal_search_clear {
height: 18px;
margin: 17px 0 0 16px;
.image-2x('../img/icons/ProfileIcons.png', 40px, 360px);
.image-2x('../img/icons/ProfileIcons.png', 40px, 420px);
background-position: -10px -164px;
}
@ -3667,7 +3667,7 @@ a.countries_modal_search_clear { @@ -3667,7 +3667,7 @@ a.countries_modal_search_clear {
height: 22px;
margin: 17px 0 0 13px;
.image-2x('../img/icons/ProfileIcons.png', 40px, 360px);
.image-2x('../img/icons/ProfileIcons.png', 40px, 420px);
background-position: -7px -280px;
}
@ -3682,7 +3682,7 @@ a.countries_modal_search_clear { @@ -3682,7 +3682,7 @@ a.countries_modal_search_clear {
height: 20px;
margin: 18px 0 0 16px;
.image-2x('../img/icons/ProfileIcons.png', 40px, 360px);
.image-2x('../img/icons/ProfileIcons.png', 40px, 420px);
background-position: -10px -220px;
}
@ -3728,7 +3728,7 @@ a.countries_modal_search_clear { @@ -3728,7 +3728,7 @@ a.countries_modal_search_clear {
margin-top: 5px;
position: absolute;
.image-2x('../img/icons/ProfileIcons.png', 40px, 360px);
.image-2x('../img/icons/ProfileIcons.png', 40px, 420px);
background-position: 0 0;
.md_modal_iconed_section_toggle & {
@ -3748,6 +3748,13 @@ a.countries_modal_search_clear { @@ -3748,6 +3748,13 @@ a.countries_modal_search_clear {
margin-top: 3px;
}
&_about {
width: 20px;
height: 20px;
background-position: -10px -344px;
margin-top: 0px;
}
&_notification {
width: 17px;
height: 20px;

28
app/partials/desktop/channel_edit_modal.html

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
<div class="md_simple_modal_wrap" my-modal-position>
<div class="md_simple_modal_body">
<form class="modal_simple_form" ng-submit="updateChannel()">
<h4 my-i18n="channel_edit_modal_title"></h4>
<div class="md-input-group" my-labeled-input>
<label class="md-input-label" my-i18n="channel_edit_name"></label>
<input class="md-input" my-focused type="text" ng-model="channel.title" />
</div>
<div class="md-input-group" my-labeled-input>
<label class="md-input-label" my-i18n="channel_edit_about"></label>
<input class="md-input" type="text" ng-model="channel.about" />
</div>
</form>
</div>
<div class="md_simple_modal_footer">
<button class="btn btn-md" ng-click="$dismiss()" my-i18n="modal_cancel"></button>
<button class="btn btn-md btn-md-primary" ng-class="{disabled: channel.updating}" ng-click="updateChannel()" ng-bind="channel.updating ? 'channel_edit_submit_active' : 'channel_edit_submit' | i18n" ng-disabled="channel.updating"></button>
</div>
</div>

136
app/partials/desktop/channel_modal.html

@ -0,0 +1,136 @@ @@ -0,0 +1,136 @@
<div class="chat_modal_wrap md_modal_wrap" my-modal-position>
<div class="md_modal_head">
<div class="md_modal_title_wrap">
<div class="md_modal_actions_wrap clearfix">
<a class="md_modal_action md_modal_action_close" ng-click="$close()" my-i18n="modal_close"></a>
<a class="md_modal_action" ng-if="chatFull.chat.pFlags.creator" ng-click="editChannel()" my-i18n="modal_edit"></a>
</div>
<div class="md_modal_title" my-i18n="channel_modal_info"></div>
</div>
<div class="peer_modal_profile_wrap clearfix">
<div class="peer_modal_photo_wrap pull-left" ng-switch="photo.updating">
<div ng-switch-when="true" class="peer_modal_photo md_photo_loading loading_dots">
<i></i><i></i><i></i>
</div>
<a ng-switch-default ng-click="openPhoto(chatFull.chat_photo.id, {p: -chatFull.chat.id})" class="peer_modal_photo" my-peer-photolink="::-chatFull.chat.id" img-class="peer_modal_photo" no-open="true" watch="true" ng-class="{disabled: !chatFull.chat.photo.photo_small}" ng-disabled="!chatFull.chat.photo.photo_small"></a>
</div>
<div class="peer_modal_profile">
<div class="peer_modal_profile_name" my-peer-link="-chatFull.chat.id"></div>
<div class="peer_modal_profile_description" ng-if="chatFull.participants_count > 0">
<ng-pluralize count="chatFull.participants_count"
when="group_modal_pluralize_participants">
</ng-pluralize>
</div>
</div>
</div>
</div>
<div class="md_modal_split_actions_wrap" ng-if="chatFull.chat.pFlags.creator">
<div class="md_modal_split_actions">
<div class="md_modal_split_action">
<input my-file-upload type="file" multiple="false" class="im_attach_input" size="120" multiple="false" accept="image/x-png, image/png, image/gif, image/jpeg" title="{{'group_modal_update_photo' | i18n}}" />
<i class="md_modal_split_action_camera"></i>
</div>
</div>
</div>
<div class="md_modal_body">
<div class="md_modal_sections">
<div class="md_modal_iconed_section_wrap md_modal_iconed_section_number" ng-if="chatFull.rAbout || chatFull.chat.username || chatFull.chat.pFlags.creator">
<i class="md_modal_section_icon md_modal_section_icon_about"></i>
<div class="md_modal_section_param_wrap" ng-if="chatFull.about.length > 0">
<div class="md_modal_section_param_value">
<span ng-bind-html="chatFull.rAbout"></span>
</div>
<div class="md_modal_section_param_name" my-i18n="user_modal_about"></div>
</div>
<div class="md_modal_section_param_wrap" ng-if="chatFull.chat.username">
<div class="md_modal_section_param_value">
<a class="settings_modal_username_link" ng-click="shareLink($event)" ng-bind="'https://telegram.me/' + chatFull.chat.username" ng-href="https://telegram.me/{{chatFull.chat.username}}" target="_blank"></a>
</div>
<div class="md_modal_section_param_name" my-i18n="channel_modal_share_link"></div>
</div>
<div class="md_modal_section_param_wrap" ng-if="!chatFull.chat.username &amp;&amp; chatFull.chat.pFlags.creator">
<div class="md_modal_section_param_value" ng-switch="chatFull.exported_invite._">
<a ng-switch-when="chatInviteExported" class="settings_modal_username_link" ng-click="shareLink($event)" ng-bind="chatFull.exported_invite.link" ng-href="{{chatFull.exported_invite.link}}" target="_blank"></a>
<span ng-switch-default my-i18n="channel_modal_share_loading">
<my-i18n-param name="dots"><span my-loading-dots></span></my-i18n-param>
</span>
</div>
<div class="md_modal_section_param_name" my-i18n="channel_modal_share_link"></div>
</div>
</div>
<div class="md_modal_iconed_section_wrap md_modal_iconed_section_link" ng-if="chatFull.chat.pFlags.creator || chatFull.chat.pFlags.left">
<i class="md_modal_section_icon md_modal_section_icon_person"></i>
<div class="md_modal_section_link_wrap" ng-switch="chatFull.chat.pFlags.left">
<a ng-switch-when="true" class="md_modal_section_link" ng-click="joinChannel()" my-i18n="channel_modal_join"></a>
<a ng-switch-default class="md_modal_section_link" ng-click="inviteToChannel()" my-i18n="channel_modal_add_member"></a>
</div>
</div>
<div class="md_modal_iconed_section_wrap md_modal_iconed_section_toggle">
<i class="md_modal_section_icon md_modal_section_icon_notification"></i>
<a class="md_modal_section_toggle_wrap tg_checkbox" ng-click="settings.notifications = !settings.notifications" ng-class="settings.notifications ? 'tg_checkbox_on' : ''">
<span class="icon icon-checkbox-outer"><i class="icon-checkbox-inner"></i></span>
<span class="tg_checkbox_label" my-i18n="group_modal_notifications"></span>
</a>
</div>
<div class="md_modal_iconed_section_wrap md_modal_iconed_section_link" ng-if="chatFull.chat.pFlags.creator || !chatFull.chat.pFlags.left && !chatFull.chat.pFlags.kicked">
<i class="md_modal_section_icon md_modal_section_icon_more"></i>
<div class="md_modal_section_link_wrap" ng-if="!chatFull.chat.pFlags.creator && !chatFull.chat.pFlags.left && !chatFull.chat.pFlags.kicked">
<a class="md_modal_section_link" ng-click="leaveChannel()" my-i18n="channel_modal_leave_channel"></a>
</div>
<div class="md_modal_section_link_wrap" ng-if="chatFull.chat.pFlags.creator">
<a class="md_modal_section_link md_modal_section_link_danger" ng-click="deleteChannel()" my-i18n="channel_modal_delete_channel"></a>
</div>
</div>
</div>
<div ng-if="chatFull.participants.participants.length > 0">
<div class="md_modal_section_splitter"></div>
<div class="md_modal_iconed_section_wrap md_modal_iconed_section_peers">
<i class="md_modal_section_icon md_modal_section_icon_people"></i>
<div class="md_modal_section_peers_wrap">
<div class="md_modal_list_peer_wrap clearfix" ng-repeat="participant in chatFull.participants.participants | orderBy:'-user.sortStatus'">
<a ng-if="participant.canLeave" ng-click="leaveChannel()" class="md_modal_list_peer_action pull-right" my-i18n="group_modal_menu_leave"></a>
<a ng-if="participant.canKick" ng-click="kickFromChannel(participant.user_id)" class="md_modal_list_peer_action pull-right" my-i18n="group_modal_members_kick"></a>
<a class="md_modal_list_peer_photo pull-left" my-peer-photolink="::participant.user_id" img-class="md_modal_list_peer_photo"></a>
<div class="md_modal_list_peer_name">
<a class="md_modal_list_peer_name" my-peer-link="participant.user_id"></a>
</div>
<div class="md_modal_list_peer_description" my-user-status="::participant.user_id" bot-chat-privacy="true"></div>
</div>
</div>
</div>
</div>
</div>
</div>

26
app/partials/desktop/chat_invite_link_modal.html

@ -6,18 +6,32 @@ @@ -6,18 +6,32 @@
<h4 my-i18n="group_invite_link_modal_title"></h4>
<div class="md-input-group md-textarea-group" my-labeled-input>
<label class="md-input-label" my-i18n="group_invite_link_link_label"></label>
<textarea class="md-input" ng-model="exportedInvite.link" rows="2" my-copy-field="'ui_invite_select'"></textarea>
<div ng-switch="exportedInvite.canRevoke">
<div ng-switch-when="true">
<div class="md-input-group md-textarea-group" my-labeled-input>
<label class="md-input-label" my-i18n="group_invite_link_link_label"></label>
<textarea class="md-input" ng-model="exportedInvite.link" rows="2" my-copy-field="'ui_invite_select'"></textarea>
</div>
</div>
<div ng-switch-default>
<div class="md-input-group" my-labeled-input>
<label class="md-input-label" my-i18n="group_invite_link_link_label"></label>
<input class="md-input" type="text" ng-model="exportedInvite.link" my-copy-field="'ui_invite_select'" />
</div>
</div>
</div>
</div>
</div>
<div class="md_simple_modal_footer">
<button class="btn btn-md" ng-click="$dismiss()" my-i18n="modal_cancel"></button>
<button class="btn btn-md btn-md-primary" ng-class="{disabled: exportedInvite.revoking}" ng-click="revokeLink()" ng-bind="exportedInvite.revoking ? 'group_invite_revoke_active' : 'group_invite_revoke' | i18n" ng-disabled="exportedInvite.revoking"></button>
<div class="md_simple_modal_footer" ng-switch="exportedInvite.canRevoke">
<div ng-switch-when="true">
<button class="btn btn-md" ng-click="$dismiss()" my-i18n="modal_cancel"></button>
<button class="btn btn-md btn-md-primary" ng-class="{disabled: exportedInvite.revoking}" ng-click="revokeLink()" ng-bind="exportedInvite.revoking ? 'group_invite_revoke_active' : 'group_invite_revoke' | i18n" ng-disabled="exportedInvite.revoking"></button>
</div>
</div>
</div>

2
app/partials/desktop/confirm_modal.html

@ -49,6 +49,8 @@ @@ -49,6 +49,8 @@
<my-i18n-param name="title"><strong ng-bind="title"></strong></my-i18n-param>
</div>
<div ng-switch-when="REVOKE_GROUP_INVITE_LINK" my-i18n="confirm_modal_revoke_group_link"></div>
<div ng-switch-when="REVOKE_CHANNEL_INVITE_LINK" my-i18n="confirm_modal_revoke_channel_link"></div>
<div ng-switch-when="CHANNEL_DELETE" my-i18n="confirm_modal_delete_channel_md"></div>
<span ng-switch-default ng-switch="message.length > 0">

2
app/partials/desktop/dialog.html

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
<a class="im_dialog" ng-mousedown="dialogSelect(dialogMessage.peerString, dialogMessage.unreadCount == -1 && dialogMessage.id)">
<a class="im_dialog" ng-mousedown="dialogSelect(dialogMessage.peerString, dialogMessage.unreadCount == -1 && dialogMessage.mid)">
<div class="im_dialog_meta pull-right text-right">
<div class="im_dialog_date" ng-bind="dialogMessage.dateText"></div>

2
app/partials/desktop/im.html

@ -71,7 +71,7 @@ @@ -71,7 +71,7 @@
<div class="im_dialogs_messages_wrap" ng-show="foundMessages.length > 0">
<h5 my-i18n="im_messages"></h5>
<ul class="nav nav-pills nav-stacked">
<li class="im_dialog_wrap" my-dialog dialog-message="dialogMessage" ng-repeat="dialogMessage in foundMessages track by dialogMessage.id" ng-class="{active: curDialog.peerID == dialogMessage.peerID &amp;&amp; curDialog.messageID == dialogMessage.id}"></li>
<li class="im_dialog_wrap" my-dialog dialog-message="dialogMessage" ng-repeat="dialogMessage in foundMessages track by dialogMessage.mid" ng-class="{active: curDialog.peerID == dialogMessage.peerID &amp;&amp; curDialog.messageID == dialogMessage.id}"></li>
</ul>
</div>

14
app/partials/desktop/message.html

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
<div class="im_message_outer_wrap" ng-click="toggleMessage(historyMessage.id, $event)">
<div class="im_message_outer_wrap" ng-click="toggleMessage(historyMessage.mid, $event)">
<div class="im_message_wrap clearfix" ng-switch="::historyMessage._ == 'messageService'">
@ -43,7 +43,7 @@ @@ -43,7 +43,7 @@
<a class="im_message_author" my-peer-link="historyMessage.fromID" short="historyMessage.toID > 0" color="historyMessage.toID < 0" no-watch="true"></a>
<a class="im_message_reply_wrap" my-reply-message="historyMessage.reply_to_msg" ng-if="::historyMessage.reply_to_msg_id"></a>
<a class="im_message_reply_wrap" my-reply-message="historyMessage.reply_to_msg" ng-if="::historyMessage.reply_to_mid"></a>
<div ng-if="::historyMessage.fwdFromID || false" class="im_message_fwd_from">
<a class="im_message_fwd_photo pull-left" my-peer-photolink="::historyMessage.fwdFromID" img-class="im_message_fwd_photo"></a>
@ -54,16 +54,16 @@ @@ -54,16 +54,16 @@
<div class="im_message_text" ng-if="::historyMessage.message.length || false" my-message-text="::historyMessage" dir="auto"></div>
<div ng-if="::historyMessage.media || historyMessage.id < 0 ? true : false" class="im_message_media" ng-switch="historyMessage.media._">
<div ng-if="::historyMessage.media || historyMessage.mid < 0 ? true : false" class="im_message_media" ng-switch="historyMessage.media._">
<div ng-switch-when="messageMediaPhoto" my-message-photo="historyMessage.media" message-id="historyMessage.id"></div>
<div ng-switch-when="messageMediaVideo" my-message-video="historyMessage.media" message-id="historyMessage.id"></div>
<div ng-switch-when="messageMediaDocument" my-message-document="historyMessage.media.document" message-id="historyMessage.id"></div>
<div ng-switch-when="messageMediaPhoto" my-message-photo="historyMessage.media" message-id="historyMessage.mid"></div>
<div ng-switch-when="messageMediaVideo" my-message-video="historyMessage.media" message-id="historyMessage.mid"></div>
<div ng-switch-when="messageMediaDocument" my-message-document="historyMessage.media.document" message-id="historyMessage.mid"></div>
<div ng-switch-when="messageMediaAudio" class="im_message_audio" my-audio-player audio="historyMessage.media.audio" message="historyMessage"></div>
<div ng-switch-when="messageMediaGeo" my-message-geo="historyMessage.media"></div>
<div ng-switch-when="messageMediaVenue" my-message-venue="historyMessage.media"></div>
<div ng-switch-when="messageMediaContact" class="im_message_contact" my-message-contact></div>
<div ng-switch-when="messageMediaWebPage" class="im_message_webpage" my-message-webpage="historyMessage.media.webpage" message-id="historyMessage.id"></div>
<div ng-switch-when="messageMediaWebPage" class="im_message_webpage" my-message-webpage="historyMessage.media.webpage" message-id="historyMessage.mid"></div>
<div ng-switch-when="messageMediaPending" my-message-pending></div>
<div ng-switch-when="messageMediaUnsupported">
<div class="im_message_text">

2
app/partials/desktop/reply_message.html

@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
/>
</div>
<div class="im_message_reply_author" ng-switch-default>
<span my-peer-link="replyMessage.from_id"></span>
<span my-peer-link="replyMessage.fromID" peer-watch="true"></span>
</div>
<div class="im_message_reply_body" ng-switch-default>
<span class="im_reply_message_media" ng-if="replyMessage.media" ng-switch="replyMessage.media._">

2
app/partials/mobile/dialog.html

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
<a class="im_dialog" ng-mousedown="dialogSelect(dialogMessage.peerString, dialogMessage.unreadCount == -1 && dialogMessage.id)">
<a class="im_dialog" ng-mousedown="dialogSelect(dialogMessage.peerString, dialogMessage.unreadCount == -1 && dialogMessage.mid)">
<div class="im_dialog_meta pull-right text-right">
<div class="im_dialog_date" ng-bind="dialogMessage.dateText"></div>

2
app/partials/mobile/im.html

@ -69,7 +69,7 @@ @@ -69,7 +69,7 @@
<div class="im_dialogs_messages_wrap" ng-show="foundMessages.length > 0">
<h5 my-i18n="im_messages"></h5>
<ul class="nav nav-pills nav-stacked">
<li class="im_dialog_wrap" my-dialog dialog-message="dialogMessage" ng-repeat="dialogMessage in foundMessages track by dialogMessage.id" ng-class="{active: curDialog.peerID == dialogMessage.peerID &amp;&amp; curDialog.messageID == dialogMessage.id}"></li>
<li class="im_dialog_wrap" my-dialog dialog-message="dialogMessage" ng-repeat="dialogMessage in foundMessages track by dialogMessage.mid" ng-class="{active: curDialog.peerID == dialogMessage.peerID &amp;&amp; curDialog.messageID == dialogMessage.mid}"></li>
</ul>
</div>

12
app/partials/mobile/message.html

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
<div class="im_message_outer_wrap" ng-click="toggleMessage(historyMessage.id, $event)">
<div class="im_message_outer_wrap" ng-click="toggleMessage(historyMessage.mid, $event)">
<div class="im_message_wrap clearfix" ng-switch="::historyMessage._ == 'messageService'">
@ -30,14 +30,14 @@ @@ -30,14 +30,14 @@
<div class="im_message_meta">
<i class="icon-message-status-tick"></i>
<span class="im_message_date" ng-bind="::historyMessage.date | time"></span>
<span class="im_message_date" ng-bind="::mhistoryMessage.date | time"></span>
</div>
<div class="im_message_body" ng-class="::{im_message_body_media: !!historyMessage.media && !historyMessage.media.rCaption}">
<a class="im_message_author" my-peer-link="historyMessage.from_id" short="!historyMessage.to_id.chat_id" color="historyMessage.to_id.chat_id > 0" no-watch="true"></a>
<a class="im_message_reply_wrap" my-reply-message="historyMessage.reply_to_msg" ng-if="::historyMessage.reply_to_msg_id"></a>
<a class="im_message_reply_wrap" my-reply-message="historyMessage.reply_to_msg" ng-if="::historyMessage.reply_to_mid"></a>
<div ng-if="::historyMessage.fwd_from_id > 0 &amp;&amp; !historyMessage.media" class="im_message_fwd_header" my-i18n="message_forwarded_message_mobile">
<a my-i18n-param="from" class="im_message_fwd_author" my-peer-link="historyMessage.fwd_from_id" no-watch="true"></a>
@ -46,9 +46,9 @@ @@ -46,9 +46,9 @@
<div ng-if="::historyMessage.media || false" class="im_message_media" ng-switch="historyMessage.media._">
<div ng-switch-when="messageMediaPhoto" my-message-photo="historyMessage.media" message-id="historyMessage.id"></div>
<div ng-switch-when="messageMediaVideo" my-message-video="historyMessage.media" message-id="historyMessage.id"></div>
<div ng-switch-when="messageMediaDocument" my-message-document="historyMessage.media.document" message-id="historyMessage.id"></div>
<div ng-switch-when="messageMediaPhoto" my-message-photo="historyMessage.media" message-id="historyMessage.mid"></div>
<div ng-switch-when="messageMediaVideo" my-message-video="historyMessage.media" message-id="historyMessage.mid"></div>
<div ng-switch-when="messageMediaDocument" my-message-document="historyMessage.media.document" message-id="historyMessage.mid"></div>
<div ng-switch-when="messageMediaAudio" class="im_message_audio" my-audio-player audio="historyMessage.media.audio" message="historyMessage"></div>
<div ng-switch-when="messageMediaGeo" my-message-geo="historyMessage.media"></div>
<div ng-switch-when="messageMediaVenue" my-message-geo="historyMessage.media"></div>

Loading…
Cancel
Save