Telegram Web, preconfigured for usage in I2P.
http://web.telegram.i2p/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3325 lines
104 KiB
3325 lines
104 KiB
/*! |
|
* Webogram v0.4.1 - messaging web application for MTProto |
|
* https://github.com/zhukov/webogram |
|
* Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com> |
|
* https://github.com/zhukov/webogram/blob/master/LICENSE |
|
*/ |
|
|
|
'use strict'; |
|
|
|
/* Controllers */ |
|
|
|
angular.module('myApp.controllers', ['myApp.i18n']) |
|
|
|
.controller('AppWelcomeController', function($scope, $location, MtpApiManager, ErrorService, ChangelogNotifyService, LayoutSwitchService) { |
|
MtpApiManager.getUserID().then(function (id) { |
|
if (id) { |
|
$location.url('/im'); |
|
return; |
|
} |
|
if (location.protocol == 'http:' && |
|
!Config.Modes.http && |
|
Config.App.domains.indexOf(location.hostname) != -1) { |
|
location.href = location.href.replace(/^http:/, 'https:'); |
|
return; |
|
} |
|
$location.url('/login'); |
|
}); |
|
|
|
ChangelogNotifyService.checkUpdate(); |
|
LayoutSwitchService.start(); |
|
}) |
|
|
|
.controller('AppLoginController', function ($scope, $rootScope, $location, $timeout, $modal, $modalStack, MtpApiManager, ErrorService, NotificationsManager, ChangelogNotifyService, IdleManager, LayoutSwitchService, TelegramMeWebService, _) { |
|
|
|
$modalStack.dismissAll(); |
|
IdleManager.start(); |
|
|
|
MtpApiManager.getUserID().then(function (id) { |
|
if (id) { |
|
$location.url('/im'); |
|
return; |
|
} |
|
if (location.protocol == 'http:' && |
|
!Config.Modes.http && |
|
Config.App.domains.indexOf(location.hostname) != -1) { |
|
location.href = location.href.replace(/^http:/, 'https:'); |
|
return; |
|
} |
|
TelegramMeWebService.setAuthorized(false); |
|
}); |
|
|
|
var options = {dcID: 2, createNetworker: true}, |
|
countryChanged = false, |
|
selectedCountry = false; |
|
|
|
$scope.credentials = {phone_country: '', phone_country_name: '', phone_number: '', phone_full: ''}; |
|
$scope.progress = {}; |
|
$scope.callPending = {}; |
|
$scope.about = {}; |
|
|
|
$scope.chooseCountry = function () { |
|
var modal = $modal.open({ |
|
templateUrl: templateUrl('country_select_modal'), |
|
controller: 'CountrySelectModalController', |
|
windowClass: 'countries_modal_window mobile_modal' |
|
}); |
|
|
|
modal.result.then(selectCountry); |
|
}; |
|
|
|
function initPhoneCountry () { |
|
var langCode = (navigator.language || '').toLowerCase(), |
|
countryIso2 = Config.LangCountries[langCode], |
|
shouldPregenerate = !Config.Navigator.mobile; |
|
|
|
if (['en', 'en-us', 'en-uk'].indexOf(langCode) == -1) { |
|
if (countryIso2 !== undefined) { |
|
selectPhoneCountryByIso2(countryIso2); |
|
} else if (langCode.indexOf('-') > 0) { |
|
selectPhoneCountryByIso2(langCode.split('-')[1].toUpperCase()); |
|
} else { |
|
selectPhoneCountryByIso2('US'); |
|
} |
|
} else { |
|
selectPhoneCountryByIso2('US'); |
|
} |
|
|
|
if (!shouldPregenerate) { |
|
return; |
|
} |
|
var wasCountry = $scope.credentials.phone_country; |
|
MtpApiManager.invokeApi('help.getNearestDc', {}, {dcID: 2, createNetworker: true}).then(function (nearestDcResult) { |
|
if (wasCountry == $scope.credentials.phone_country) { |
|
selectPhoneCountryByIso2(nearestDcResult.country); |
|
} |
|
if (nearestDcResult.nearest_dc != nearestDcResult.this_dc) { |
|
MtpApiManager.getNetworker(nearestDcResult.nearest_dc, {createNetworker: true}); |
|
} |
|
}); |
|
} |
|
|
|
function selectPhoneCountryByIso2 (countryIso2) { |
|
var i, country; |
|
for (i = 0; i < Config.CountryCodes.length; i++) { |
|
country = Config.CountryCodes[i]; |
|
if (country[0] == countryIso2) { |
|
return selectCountry({name: _(country[1] + '_raw'), code: country[2]}); |
|
} |
|
} |
|
return selectCountry({name: _('country_select_modal_country_us_raw'), code: '+1'}); |
|
} |
|
|
|
function selectCountry (country) { |
|
selectedCountry = country; |
|
if ($scope.credentials.phone_country != country.code) { |
|
$scope.credentials.phone_country = country.code; |
|
} else { |
|
updateCountry(); |
|
} |
|
$scope.$broadcast('country_selected'); |
|
$scope.$broadcast('value_updated'); |
|
} |
|
|
|
function updateCountry () { |
|
var phoneNumber = ( |
|
($scope.credentials.phone_country || '') + |
|
($scope.credentials.phone_number || '') |
|
).replace(/\D+/g, ''), |
|
i, j, code, |
|
maxLength = 0, |
|
maxName = false; |
|
|
|
if (phoneNumber.length) { |
|
if (selectedCountry && !phoneNumber.indexOf(selectedCountry.code.replace(/\D+/g, ''))) { |
|
maxName = selectedCountry.name; |
|
} else { |
|
for (i = 0; i < Config.CountryCodes.length; i++) { |
|
for (j = 2; j < Config.CountryCodes[i].length; j++) { |
|
code = Config.CountryCodes[i][j].replace(/\D+/g, ''); |
|
if (code.length > maxLength && !phoneNumber.indexOf(code)) { |
|
maxLength = code.length; |
|
maxName = _(Config.CountryCodes[i][1] + '_raw'); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
$scope.credentials.phone_full = phoneNumber; |
|
$scope.credentials.phone_country_name = maxName || _('login_controller_unknown_country_raw'); |
|
}; |
|
|
|
$scope.$watch('credentials.phone_country', updateCountry); |
|
$scope.$watch('credentials.phone_number', updateCountry); |
|
initPhoneCountry(); |
|
|
|
|
|
var callTimeout; |
|
|
|
function saveAuth (result) { |
|
MtpApiManager.setUserAuth(options.dcID, { |
|
expires: result.expires, |
|
id: result.user.id |
|
}); |
|
$timeout.cancel(callTimeout); |
|
|
|
$location.url('/im'); |
|
}; |
|
|
|
function callCheck () { |
|
$timeout.cancel(callTimeout); |
|
if ($scope.credentials.viaApp) { |
|
return; |
|
} |
|
if (!(--$scope.callPending.remaining)) { |
|
$scope.callPending.success = false; |
|
MtpApiManager.invokeApi('auth.sendCall', { |
|
phone_number: $scope.credentials.phone_full, |
|
phone_code_hash: $scope.credentials.phone_code_hash |
|
}, options).then(function () { |
|
$scope.callPending.success = true; |
|
}); |
|
} else { |
|
callTimeout = $timeout(callCheck, 1000); |
|
} |
|
} |
|
|
|
$scope.sendCode = function () { |
|
$timeout.cancel(callTimeout); |
|
|
|
ErrorService.confirm({ |
|
type: 'LOGIN_PHONE_CORRECT', |
|
country_code: $scope.credentials.phone_country, |
|
phone_number: $scope.credentials.phone_number |
|
}).then(function () { |
|
$scope.progress.enabled = true; |
|
|
|
onContentLoaded(function () { |
|
$scope.$broadcast('ui_height'); |
|
}); |
|
|
|
var authKeyStarted = tsNow(); |
|
MtpApiManager.invokeApi('auth.sendCode', { |
|
phone_number: $scope.credentials.phone_full, |
|
// sms_type: 5, |
|
api_id: Config.App.id, |
|
api_hash: Config.App.hash |
|
}, options).then(function (sentCode) { |
|
$scope.progress.enabled = false; |
|
|
|
$scope.credentials.phone_code_hash = sentCode.phone_code_hash; |
|
$scope.credentials.phone_occupied = sentCode.phone_registered; |
|
$scope.credentials.viaApp = sentCode._ == 'auth.sentAppCode'; |
|
$scope.callPending.remaining = sentCode.send_call_timeout || 60; |
|
$scope.error = {}; |
|
$scope.about = {}; |
|
|
|
callCheck(); |
|
|
|
onContentLoaded(function () { |
|
$scope.$broadcast('ui_height'); |
|
}); |
|
|
|
}, function (error) { |
|
$scope.progress.enabled = false; |
|
console.log('sendCode error', error); |
|
switch (error.type) { |
|
case 'PHONE_NUMBER_INVALID': |
|
$scope.error = {field: 'phone'}; |
|
error.handled = true; |
|
break; |
|
} |
|
})['finally'](function () { |
|
if ($rootScope.idle.isIDLE || tsNow() - authKeyStarted > 60000) { |
|
NotificationsManager.notify({ |
|
title: 'Telegram', |
|
message: 'Your authorization key was successfully generated! Open the app to log in.', |
|
tag: 'auth_key' |
|
}); |
|
} |
|
}); |
|
}); |
|
} |
|
|
|
$scope.sendSms = function () { |
|
if (!$scope.credentials.viaApp) { |
|
return; |
|
} |
|
delete $scope.credentials.viaApp; |
|
MtpApiManager.invokeApi('auth.sendSms', { |
|
phone_number: $scope.credentials.phone_full, |
|
phone_code_hash: $scope.credentials.phone_code_hash |
|
}, options).then(callCheck); |
|
} |
|
|
|
$scope.editPhone = function () { |
|
$timeout.cancel(callTimeout); |
|
|
|
delete $scope.credentials.phone_code_hash; |
|
delete $scope.credentials.phone_unoccupied; |
|
delete $scope.credentials.phone_code_valid; |
|
delete $scope.credentials.viaApp; |
|
delete $scope.callPending.remaining; |
|
delete $scope.callPending.success; |
|
} |
|
|
|
$scope.logIn = function (forceSignUp) { |
|
var method = 'auth.signIn', params = { |
|
phone_number: $scope.credentials.phone_full, |
|
phone_code_hash: $scope.credentials.phone_code_hash, |
|
phone_code: $scope.credentials.phone_code |
|
}; |
|
if (forceSignUp) { |
|
method = 'auth.signUp'; |
|
angular.extend(params, { |
|
first_name: $scope.credentials.first_name || '', |
|
last_name: $scope.credentials.last_name || '' |
|
}); |
|
} |
|
|
|
$scope.progress.enabled = true; |
|
MtpApiManager.invokeApi(method, params, options).then(saveAuth, function (error) { |
|
$scope.progress.enabled = false; |
|
if (error.code == 400 && error.type == 'PHONE_NUMBER_UNOCCUPIED') { |
|
error.handled = true; |
|
$scope.credentials.phone_code_valid = true; |
|
$scope.credentials.phone_unoccupied = true; |
|
$scope.about = {}; |
|
return; |
|
} else if (error.code == 400 && error.type == 'PHONE_NUMBER_OCCUPIED') { |
|
error.handled = true; |
|
return $scope.logIn(false); |
|
} |
|
|
|
|
|
switch (error.type) { |
|
case 'FIRSTNAME_INVALID': |
|
$scope.error = {field: 'first_name'}; |
|
error.handled = true; |
|
break; |
|
case 'LASTNAME_INVALID': |
|
$scope.error = {field: 'last_name'}; |
|
error.handled = true; |
|
break; |
|
case 'PHONE_CODE_INVALID': |
|
$scope.error = {field: 'phone_code'}; |
|
delete $scope.credentials.phone_code_valid; |
|
error.handled = true; |
|
break; |
|
} |
|
}); |
|
|
|
}; |
|
|
|
ChangelogNotifyService.checkUpdate(); |
|
LayoutSwitchService.start(); |
|
}) |
|
|
|
.controller('AppIMController', function ($scope, $location, $routeParams, $modal, $rootScope, $modalStack, MtpApiManager, AppUsersManager, AppChatsManager, AppPeersManager, ContactsSelectService, ChangelogNotifyService, ErrorService, AppRuntimeManager, HttpsMigrateService, LayoutSwitchService, LocationParamsService, AppStickersManager) { |
|
|
|
$scope.$on('$routeUpdate', updateCurDialog); |
|
|
|
$scope.$on('history_focus', function (e, peerData) { |
|
$modalStack.dismissAll(); |
|
if (peerData.peerString == $scope.curDialog.peer && peerData.messageID == $scope.curDialog.messageID) { |
|
$scope.$broadcast(peerData.messageID ? 'ui_history_change_scroll' : 'ui_history_focus'); |
|
} else { |
|
var peerID = AppPeersManager.getPeerID(peerData.peerString); |
|
var peer = peerData.peerString; |
|
if (peerID > 0) { |
|
var username = AppUsersManager.getUser(peerID).username; |
|
if (username) { |
|
peer = '@' + username; |
|
} |
|
} |
|
$location.url('/im?p=' + peer + (peerData.messageID ? '&m=' + peerData.messageID : '')); |
|
} |
|
}); |
|
|
|
$scope.$on('esc_no_more', function () { |
|
$rootScope.$apply(function () { |
|
$location.url('/im'); |
|
}) |
|
}); |
|
|
|
|
|
$scope.isLoggedIn = true; |
|
$scope.isEmpty = {}; |
|
$scope.search = {}; |
|
$scope.historyFilter = {mediaType: false}; |
|
$scope.historyPeer = {}; |
|
$scope.historyState = { |
|
selectActions: false, |
|
typing: [], |
|
missedCount: 0, |
|
skipped: false |
|
}; |
|
|
|
$scope.openSettings = function () { |
|
$modal.open({ |
|
templateUrl: templateUrl('settings_modal'), |
|
controller: 'SettingsModalController', |
|
windowClass: 'settings_modal_window mobile_modal' |
|
}); |
|
}; |
|
|
|
$scope.openFaq = function () { |
|
var url = 'https://telegram.org/faq'; |
|
switch (Config.I18n.locale) { |
|
case 'es-es': url += '/es'; break; |
|
case 'it-it': url += '/it'; break; |
|
case 'de-de': url += '/de'; break; |
|
case 'ko-ko': url += '/ko'; break; |
|
case 'pt-br': url += '/br'; break; |
|
}; |
|
window.open(url, '_blank'); |
|
}; |
|
|
|
$scope.openContacts = function () { |
|
ContactsSelectService.selectContact().then(function (userID) { |
|
$scope.dialogSelect(AppUsersManager.getUserString(userID)); |
|
}); |
|
}; |
|
|
|
$scope.openGroup = function () { |
|
ContactsSelectService.selectContacts({action: 'new_group'}).then(function (userIDs) { |
|
|
|
if (userIDs.length == 1) { |
|
$scope.dialogSelect(AppUsersManager.getUserString(userIDs[0])); |
|
} else if (userIDs.length > 1) { |
|
var scope = $rootScope.$new(); |
|
scope.userIDs = userIDs; |
|
|
|
$modal.open({ |
|
templateUrl: templateUrl('chat_create_modal'), |
|
controller: 'ChatCreateModalController', |
|
scope: scope, |
|
windowClass: 'md_simple_modal_window mobile_modal' |
|
}); |
|
} |
|
|
|
}); |
|
}; |
|
|
|
$scope.importContact = function () { |
|
AppUsersManager.openImportContact().then(function (foundContact) { |
|
if (foundContact) { |
|
$rootScope.$broadcast('history_focus', { |
|
peerString: AppUsersManager.getUserString(foundContact) |
|
}); |
|
} |
|
}); |
|
}; |
|
|
|
$scope.searchClear = function () { |
|
$scope.search.query = ''; |
|
$scope.$broadcast('search_clear'); |
|
} |
|
|
|
$scope.dialogSelect = function (peerString, messageID) { |
|
var params = {peerString: peerString}; |
|
if (messageID) { |
|
params.messageID = messageID; |
|
} |
|
else if ($scope.search.query) { |
|
$scope.searchClear(); |
|
} |
|
$rootScope.$broadcast('history_focus', params); |
|
}; |
|
|
|
$scope.logOut = function () { |
|
ErrorService.confirm({type: 'LOGOUT'}).then(function () { |
|
MtpApiManager.logOut().then(function () { |
|
location.hash = '/login'; |
|
AppRuntimeManager.reload(); |
|
}); |
|
}) |
|
}; |
|
|
|
$scope.openChangelog = function () { |
|
ChangelogNotifyService.showChangelog(false); |
|
} |
|
|
|
$scope.showPeerInfo = function () { |
|
if ($scope.curDialog.peerID > 0) { |
|
AppUsersManager.openUser($scope.curDialog.peerID) |
|
} else if ($scope.curDialog.peerID < 0) { |
|
AppChatsManager.openChat(-$scope.curDialog.peerID) |
|
} |
|
}; |
|
|
|
$scope.toggleEdit = function () { |
|
$scope.$broadcast('history_edit_toggle'); |
|
}; |
|
$scope.selectedFlush = function () { |
|
$scope.$broadcast('history_edit_flush'); |
|
}; |
|
$scope.toggleMedia = function (mediaType) { |
|
$scope.$broadcast('history_media_toggle', mediaType); |
|
}; |
|
$scope.returnToRecent = function () { |
|
$scope.$broadcast('history_return_recent'); |
|
}; |
|
$scope.toggleSearch = function () { |
|
$scope.$broadcast('dialogs_search_toggle'); |
|
}; |
|
|
|
updateCurDialog(); |
|
|
|
var lastSearch = false; |
|
function updateCurDialog() { |
|
if ($routeParams.q) { |
|
if ($routeParams.q !== lastSearch) { |
|
$scope.search.query = lastSearch = $routeParams.q; |
|
if ($scope.curDialog !== undefined) { |
|
return false; |
|
} |
|
} |
|
} else { |
|
lastSearch = false; |
|
} |
|
if ($routeParams.p && $routeParams.p.charAt(0) == '@') { |
|
if ($scope.curDialog === undefined) { |
|
$scope.curDialog = {}; |
|
} |
|
AppUsersManager.resolveUsername($routeParams.p.substr(1)).then(function (userID) { |
|
$scope.curDialog = { |
|
peer: AppUsersManager.getUserString(userID), |
|
messageID: $routeParams.m || false |
|
}; |
|
}); |
|
} else { |
|
$scope.curDialog = { |
|
peer: $routeParams.p || false, |
|
messageID: $routeParams.m || false |
|
}; |
|
} |
|
} |
|
|
|
ChangelogNotifyService.checkUpdate(); |
|
HttpsMigrateService.start(); |
|
LayoutSwitchService.start(); |
|
LocationParamsService.start(); |
|
AppStickersManager.start(); |
|
}) |
|
|
|
.controller('AppImDialogsController', function ($scope, $location, $q, $timeout, $routeParams, MtpApiManager, AppUsersManager, AppChatsManager, AppMessagesManager, AppPeersManager, PhonebookContactsService, ErrorService, AppRuntimeManager) { |
|
|
|
$scope.dialogs = []; |
|
$scope.contacts = []; |
|
$scope.foundUsers = []; |
|
$scope.foundMessages = []; |
|
|
|
if ($scope.search === undefined) { |
|
$scope.search = {}; |
|
} |
|
if ($scope.isEmpty === undefined) { |
|
$scope.isEmpty = {}; |
|
} |
|
$scope.phonebookAvailable = PhonebookContactsService.isAvailable(); |
|
|
|
var searchMessages = false; |
|
var maxID = 0; |
|
var hasMore = false; |
|
var jump = 0; |
|
var contactsJump = 0; |
|
var peersInDialogs = {}; |
|
var typingTimeouts = {}; |
|
var contactsShown; |
|
|
|
$scope.$on('dialogs_need_more', function () { |
|
// console.log('on need more'); |
|
showMoreDialogs(); |
|
}); |
|
|
|
$scope.$on('dialog_unread', function (e, dialog) { |
|
angular.forEach($scope.dialogs, function(curDialog) { |
|
if (curDialog.peerID == dialog.peerID) { |
|
curDialog.unreadCount = dialog.count; |
|
} |
|
}); |
|
}); |
|
|
|
$scope.$on('dialogs_update', function (e, dialog) { |
|
if ($scope.search.query !== undefined && $scope.search.query.length) { |
|
return false; |
|
} |
|
|
|
var pos = false; |
|
angular.forEach($scope.dialogs, function(curDialog, curPos) { |
|
if (curDialog.peerID == dialog.peerID) { |
|
pos = curPos; |
|
} |
|
}); |
|
|
|
var wrappedDialog = AppMessagesManager.wrapForDialog(dialog.top_message, dialog.unread_count); |
|
if (pos !== false) { |
|
var prev = $scope.dialogs.splice(pos, 1); |
|
safeReplaceObject(prev, wrappedDialog); |
|
} |
|
$scope.dialogs.unshift(wrappedDialog); |
|
delete $scope.isEmpty.dialogs; |
|
|
|
if (!peersInDialogs[dialog.peerID]) { |
|
peersInDialogs[dialog.peerID] = true; |
|
if (contactsShown) { |
|
showMoreConversations(); |
|
} |
|
} |
|
|
|
}); |
|
|
|
$scope.$on('dialog_flush', function (e, dialog) { |
|
for (var i = 0; i < $scope.dialogs.length; i++) { |
|
if ($scope.dialogs[i].peerID == dialog.peerID) { |
|
$scope.dialogs.splice(i, 1); |
|
break; |
|
} |
|
} |
|
}); |
|
|
|
$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]) { |
|
$scope.dialogs[i].deleted = true; |
|
} |
|
break; |
|
} |
|
} |
|
}); |
|
|
|
$scope.$on('apiUpdate', function (e, update) { |
|
switch (update._) { |
|
case 'updateUserTyping': |
|
case 'updateChatUserTyping': |
|
if (!AppUsersManager.hasUser(update.user_id)) { |
|
if (update.chat_id) { |
|
AppChatsManager.getChatFull(update.chat_id); |
|
} |
|
return; |
|
} |
|
var peerID = update._ == 'updateUserTyping'? update.user_id : -update.chat_id; |
|
AppUsersManager.forceUserOnline(update.user_id); |
|
for (var i = 0; i < $scope.dialogs.length; i++) { |
|
if ($scope.dialogs[i].peerID == peerID) { |
|
$scope.dialogs[i].typing = update.user_id; |
|
$timeout.cancel(typingTimeouts[peerID]); |
|
|
|
typingTimeouts[peerID] = $timeout(function () { |
|
for (var i = 0; i < $scope.dialogs.length; i++) { |
|
if ($scope.dialogs[i].peerID == peerID) { |
|
if ($scope.dialogs[i].typing == update.user_id) { |
|
delete $scope.dialogs[i].typing; |
|
} |
|
} |
|
} |
|
}, 6000); |
|
break; |
|
} |
|
} |
|
break; |
|
} |
|
}); |
|
|
|
$scope.$watchCollection('search', function () { |
|
$scope.dialogs = []; |
|
$scope.foundMessages = []; |
|
searchMessages = false; |
|
contactsJump++; |
|
loadDialogs(); |
|
|
|
if ($routeParams.q && $scope.search.query != $routeParams.q) { |
|
$timeout(function () { |
|
$location.url( |
|
'/im' + |
|
($scope.curDialog.peer |
|
? '?p=' + $scope.curDialog.peer + |
|
($scope.curDialog.messageID ? '&m=' + $scope.curDialog.messageID : '') |
|
: '' |
|
) |
|
); |
|
}); |
|
} |
|
}); |
|
|
|
if (Config.Mobile) { |
|
$scope.$watch('curDialog.peer', function () { |
|
$scope.$broadcast('ui_dialogs_update') |
|
}); |
|
} |
|
|
|
$scope.importPhonebook = function () { |
|
PhonebookContactsService.openPhonebookImport(); |
|
}; |
|
|
|
$scope.$on('contacts_update', function () { |
|
if (contactsShown) { |
|
showMoreConversations(); |
|
} |
|
}); |
|
|
|
$scope.$on('ui_dialogs_search_clear', $scope.searchClear); |
|
|
|
var searchTimeoutPromise; |
|
function getDialogs(force) { |
|
var curJump = ++jump, |
|
promise; |
|
|
|
$timeout.cancel(searchTimeoutPromise); |
|
if (searchMessages) { |
|
searchTimeoutPromise = (force || maxID) ? $q.when() : $timeout(angular.noop, 500); |
|
promise = searchTimeoutPromise.then(function () { |
|
return AppMessagesManager.getSearch({_: 'inputPeerEmpty'}, $scope.search.query, {_: 'inputMessagesFilterEmpty'}, maxID); |
|
}); |
|
} else { |
|
promise = AppMessagesManager.getDialogs($scope.search.query, maxID); |
|
} |
|
|
|
return promise.then(function (result) { |
|
if (curJump != jump) { |
|
return $q.reject(); |
|
} |
|
if (searchMessages) { |
|
var dialogs = []; |
|
angular.forEach(result.history, function (messageID) { |
|
var message = AppMessagesManager.getMessage(messageID), |
|
peerID = AppMessagesManager.getMessagePeer(message); |
|
|
|
dialogs.push({ |
|
peerID: peerID, |
|
top_message: messageID, |
|
unread_count: -1 |
|
}); |
|
}); |
|
|
|
result = { |
|
count: result.count, |
|
dialogs: dialogs |
|
}; |
|
} |
|
|
|
return result; |
|
}, function (error) { |
|
if (error.code == 401) { |
|
MtpApiManager.logOut()['finally'](function () { |
|
if (location.protocol == 'http:' && |
|
!Config.Modes.http && |
|
Config.App.domains.indexOf(location.hostname) != -1) { |
|
location.href = location.href.replace(/^http:/, 'https:'); |
|
} else { |
|
location.hash = '/login'; |
|
AppRuntimeManager.reload(); |
|
} |
|
}); |
|
error.handled = true; |
|
} |
|
|
|
return $q.reject(); |
|
}); |
|
}; |
|
|
|
function loadDialogs (force) { |
|
maxID = 0; |
|
hasMore = false; |
|
if (!searchMessages) { |
|
peersInDialogs = {}; |
|
contactsShown = false; |
|
} |
|
|
|
getDialogs(force).then(function (dialogsResult) { |
|
if (!searchMessages) { |
|
$scope.dialogs = []; |
|
$scope.contacts = []; |
|
$scope.foundUsers = []; |
|
} |
|
$scope.foundMessages = []; |
|
|
|
var dialogsList = searchMessages ? $scope.foundMessages : $scope.dialogs; |
|
|
|
if (dialogsResult.dialogs.length) { |
|
angular.forEach(dialogsResult.dialogs, function (dialog) { |
|
var wrappedDialog = AppMessagesManager.wrapForDialog(dialog.top_message, dialog.unread_count); |
|
if (!searchMessages) { |
|
peersInDialogs[dialog.peerID] = true; |
|
} |
|
dialogsList.push(wrappedDialog); |
|
}); |
|
|
|
maxID = dialogsResult.dialogs[dialogsResult.dialogs.length - 1].top_message; |
|
hasMore = dialogsResult.count === null || dialogsList.length < dialogsResult.count; |
|
|
|
if (!searchMessages) { |
|
delete $scope.isEmpty.dialogs; |
|
} |
|
} |
|
|
|
$scope.$broadcast('ui_dialogs_change'); |
|
|
|
if (!$scope.search.query) { |
|
AppMessagesManager.getDialogs('', maxID, 100); |
|
if (!dialogsResult.dialogs.length) { |
|
$scope.isEmpty.dialogs = true; |
|
showMoreDialogs(); |
|
} |
|
} else { |
|
showMoreDialogs(); |
|
} |
|
|
|
}); |
|
} |
|
|
|
function showMoreDialogs () { |
|
if (contactsShown && (!hasMore || !maxID)) { |
|
return; |
|
} |
|
|
|
if (!hasMore && !searchMessages && ($scope.search.query || !$scope.dialogs.length)) { |
|
showMoreConversations(); |
|
return; |
|
} |
|
|
|
getDialogs().then(function (dialogsResult) { |
|
if (dialogsResult.dialogs.length) { |
|
var dialogsList = searchMessages ? $scope.foundMessages : $scope.dialogs; |
|
|
|
angular.forEach(dialogsResult.dialogs, function (dialog) { |
|
var wrappedDialog = AppMessagesManager.wrapForDialog(dialog.top_message, dialog.unread_count); |
|
if (!searchMessages) { |
|
peersInDialogs[dialog.peerID] = true; |
|
} |
|
dialogsList.push(wrappedDialog); |
|
}); |
|
|
|
maxID = dialogsResult.dialogs[dialogsResult.dialogs.length - 1].top_message; |
|
hasMore = dialogsResult.count === null || dialogsList.length < dialogsResult.count; |
|
|
|
$scope.$broadcast('ui_dialogs_append'); |
|
} |
|
}); |
|
}; |
|
|
|
function showMoreConversations () { |
|
contactsShown = true; |
|
|
|
var curJump = ++contactsJump; |
|
AppUsersManager.getContacts($scope.search.query).then(function (contactsList) { |
|
if (curJump != contactsJump) return; |
|
$scope.contacts = []; |
|
angular.forEach(contactsList, function(userID) { |
|
if (peersInDialogs[userID] === undefined) { |
|
$scope.contacts.push({ |
|
userID: userID, |
|
user: AppUsersManager.getUser(userID), |
|
peerString: AppUsersManager.getUserString(userID) |
|
}); |
|
} |
|
}); |
|
|
|
if (contactsList.length) { |
|
delete $scope.isEmpty.contacts; |
|
} else if (!$scope.search.query) { |
|
$scope.isEmpty.contacts = true; |
|
} |
|
$scope.$broadcast('ui_dialogs_append'); |
|
}); |
|
|
|
if ($scope.search.query && $scope.search.query.length >= 5) { |
|
$timeout(function() { |
|
if (curJump != contactsJump) return; |
|
MtpApiManager.invokeApi('contacts.search', {q: $scope.search.query, limit: 10}).then(function (result) { |
|
AppUsersManager.saveApiUsers(result.users); |
|
if (curJump != contactsJump) return; |
|
$scope.foundUsers = []; |
|
angular.forEach(result.results, function(contactFound) { |
|
var userID = contactFound.user_id; |
|
if (peersInDialogs[userID] === undefined) { |
|
$scope.foundUsers.push({ |
|
userID: userID, |
|
user: AppUsersManager.getUser(userID), |
|
peerString: AppUsersManager.getUserString(userID) |
|
}); |
|
} |
|
}); |
|
}, function (error) { |
|
if (error.code == 400) { |
|
error.handled = true; |
|
} |
|
}); |
|
}, 500); |
|
} |
|
|
|
if ($scope.search.query) { |
|
searchMessages = true; |
|
loadDialogs(); |
|
} |
|
} |
|
|
|
}) |
|
|
|
.controller('AppImHistoryController', function ($scope, $location, $timeout, $rootScope, MtpApiManager, AppUsersManager, AppChatsManager, AppMessagesManager, AppPeersManager, ApiUpdatesManager, PeersSelectService, IdleManager, StatusManager, ErrorService) { |
|
|
|
$scope.$watch('curDialog', applyDialogSelect); |
|
|
|
ApiUpdatesManager.attach(); |
|
IdleManager.start(); |
|
StatusManager.start(); |
|
|
|
$scope.peerHistories = []; |
|
$scope.selectedMsgs = {}; |
|
$scope.selectedCount = 0; |
|
$scope.historyState.selectActions = false; |
|
$scope.historyState.missedCount = 0; |
|
$scope.historyState.skipped = false; |
|
$scope.state = {}; |
|
|
|
$scope.toggleMessage = toggleMessage; |
|
$scope.selectedDelete = selectedDelete; |
|
$scope.selectedForward = selectedForward; |
|
$scope.selectedReply = selectedReply; |
|
$scope.selectedCancel = selectedCancel; |
|
$scope.selectedFlush = selectedFlush; |
|
|
|
$scope.toggleEdit = toggleEdit; |
|
$scope.toggleMedia = toggleMedia; |
|
$scope.returnToRecent = returnToRecent; |
|
|
|
$scope.$on('history_edit_toggle', toggleEdit); |
|
$scope.$on('history_edit_flush', selectedFlush); |
|
$scope.$on('history_media_toggle', function (e, mediaType) { |
|
toggleMedia(mediaType); |
|
}); |
|
|
|
|
|
$scope.$on('history_return_recent', returnToRecent); |
|
|
|
var peerID, |
|
peerHistory = false, |
|
unreadAfterIdle = false, |
|
hasMore = false, |
|
hasLess = false, |
|
maxID = 0, |
|
minID = 0, |
|
lastSelectID = false, |
|
inputMediaFilters = { |
|
photos: 'inputMessagesFilterPhotos', |
|
video: 'inputMessagesFilterVideo', |
|
documents: 'inputMessagesFilterDocument', |
|
audio: 'inputMessagesFilterAudio' |
|
}, |
|
jump = 0, |
|
moreJump = 0, |
|
moreActive = false, |
|
morePending = false, |
|
lessJump = 0, |
|
lessActive = false, |
|
lessPending = false; |
|
|
|
function applyDialogSelect (newDialog, oldDialog) { |
|
var newPeer = newDialog.peer || $scope.curDialog.peer || ''; |
|
peerID = AppPeersManager.getPeerID(newPeer); |
|
|
|
|
|
if (peerID == $scope.curDialog.peerID && oldDialog.messageID == newDialog.messageID) { |
|
return false; |
|
} |
|
|
|
$rootScope.selectedPeerID = peerID; |
|
$scope.curDialog.peerID = peerID; |
|
$scope.curDialog.inputPeer = AppPeersManager.getInputPeer(newPeer); |
|
$scope.historyFilter.mediaType = false; |
|
|
|
selectedCancel(true); |
|
|
|
if (oldDialog.peer && oldDialog.peer == newDialog.peer && newDialog.messageID) { |
|
messageFocusHistory(); |
|
} |
|
else if (peerID) { |
|
updateHistoryPeer(true); |
|
loadHistory(); |
|
} |
|
else { |
|
showEmptyHistory(); |
|
} |
|
} |
|
|
|
function historiesQueuePush (peerID) { |
|
var pos = -1, |
|
maxLen = 10, |
|
i, |
|
history, |
|
diff; |
|
|
|
for (i = 0; i < $scope.peerHistories.length; i++) { |
|
if ($scope.peerHistories[i].peerID == peerID) { |
|
pos = i; |
|
break; |
|
} |
|
} |
|
if (pos > -1) { |
|
history = $scope.peerHistories[pos]; |
|
return history; |
|
} |
|
history = {peerID: peerID, messages: []}; |
|
$scope.peerHistories.unshift(history); |
|
diff = $scope.peerHistories.length - maxLen; |
|
if (diff > 0) { |
|
$scope.peerHistories.splice(maxLen - 1, diff); |
|
} |
|
|
|
return history; |
|
} |
|
|
|
function historiesQueueFind (peerID) { |
|
var i; |
|
for (i = 0; i < $scope.peerHistories.length; i++) { |
|
if ($scope.peerHistories[i].peerID == peerID) { |
|
return $scope.peerHistories[i]; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
function updateHistoryPeer(preload) { |
|
var peerData = AppPeersManager.getPeer(peerID); |
|
// console.log('update', preload, peerData); |
|
if (!peerData || peerData.deleted) { |
|
safeReplaceObject($scope.state, {loaded: false}); |
|
return false; |
|
} |
|
|
|
peerHistory = historiesQueuePush(peerID); |
|
|
|
safeReplaceObject($scope.historyPeer, { |
|
id: peerID, |
|
data: peerData, |
|
photo: AppPeersManager.getPeerPhoto(peerID, 'User', 'Group') |
|
}); |
|
|
|
MtpApiManager.getUserID().then(function (id) { |
|
$scope.ownID = id; |
|
$scope.ownPhoto = AppUsersManager.getUserPhoto(id, 'User'); |
|
}); |
|
|
|
if (preload) { |
|
$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}); |
|
} |
|
} |
|
|
|
function messageFocusHistory () { |
|
var i, |
|
found = false, |
|
history = historiesQueueFind(); |
|
|
|
if (history) { |
|
for (i = 0; i < history.messages.length; i++) { |
|
if ($scope.curDialog.messageID == history.messages[i].id) { |
|
found = true; |
|
break; |
|
} |
|
} |
|
} |
|
|
|
if (found) { |
|
$scope.historyUnread = {}; |
|
$scope.$broadcast('messages_focus', $scope.curDialog.messageID); |
|
$scope.$broadcast('ui_history_change_scroll'); |
|
} else { |
|
loadHistory(); |
|
} |
|
} |
|
|
|
function showLessHistory () { |
|
if (!hasLess) { |
|
return; |
|
} |
|
if (moreActive) { |
|
lessPending = true; |
|
return; |
|
} |
|
lessPending = false; |
|
lessActive = true; |
|
|
|
var curJump = jump, |
|
curLessJump = ++lessJump, |
|
limit = 0, |
|
backLimit = 20; |
|
AppMessagesManager.getHistory($scope.curDialog.inputPeer, minID, limit, backLimit).then(function (historyResult) { |
|
lessActive = false; |
|
if (curJump != jump || curLessJump != lessJump) return; |
|
|
|
var i, id; |
|
for (i = historyResult.history.length - 1; i >= 0; i--) { |
|
id = historyResult.history[i]; |
|
if (id > minID) { |
|
peerHistory.messages.push(AppMessagesManager.wrapForHistory(id)); |
|
} |
|
} |
|
|
|
if (historyResult.history.length) { |
|
minID = historyResult.history.length >= backLimit |
|
? historyResult.history[0] |
|
: 0; |
|
if (AppMessagesManager.regroupWrappedHistory(peerHistory.messages, -backLimit)) { |
|
$scope.$broadcast('messages_regroup'); |
|
} |
|
delete $scope.state.empty; |
|
$scope.$broadcast('ui_history_append'); |
|
} else { |
|
minID = 0; |
|
} |
|
$scope.historyState.skipped = hasLess = minID > 0; |
|
|
|
if (morePending) { |
|
showMoreHistory(); |
|
} |
|
}); |
|
} |
|
|
|
function showMoreHistory () { |
|
if (!hasMore) { |
|
return; |
|
} |
|
if (lessActive) { |
|
morePending = true; |
|
return; |
|
} |
|
morePending = false; |
|
moreActive = true; |
|
|
|
var curJump = jump, |
|
curMoreJump = ++moreJump, |
|
inputMediaFilter = $scope.historyFilter.mediaType && {_: inputMediaFilters[$scope.historyFilter.mediaType]}, |
|
limit = Config.Mobile ? 20 : 0, |
|
getMessagesPromise = inputMediaFilter |
|
? AppMessagesManager.getSearch($scope.curDialog.inputPeer, '', inputMediaFilter, maxID, limit) |
|
: AppMessagesManager.getHistory($scope.curDialog.inputPeer, maxID, limit); |
|
|
|
getMessagesPromise.then(function (historyResult) { |
|
moreActive = false; |
|
if (curJump != jump || curMoreJump != moreJump) return; |
|
|
|
angular.forEach(historyResult.history, function (id) { |
|
peerHistory.messages.unshift(AppMessagesManager.wrapForHistory(id)); |
|
}); |
|
|
|
hasMore = historyResult.count === null || |
|
historyResult.history.length && peerHistory.messages.length < historyResult.count; |
|
|
|
if (historyResult.history.length) { |
|
delete $scope.state.empty; |
|
maxID = historyResult.history[historyResult.history.length - 1]; |
|
$scope.$broadcast('ui_history_prepend'); |
|
if (AppMessagesManager.regroupWrappedHistory(peerHistory.messages, historyResult.history.length + 1)) { |
|
$scope.$broadcast('messages_regroup'); |
|
} |
|
} |
|
|
|
if (lessPending) { |
|
showLessHistory(); |
|
} |
|
}); |
|
}; |
|
|
|
function loadHistory (forceRecent) { |
|
$scope.historyState.missedCount = 0; |
|
|
|
hasMore = false; |
|
$scope.historyState.skipped = hasLess = false; |
|
maxID = 0; |
|
minID = 0; |
|
peerHistory = historiesQueuePush(peerID); |
|
|
|
|
|
var limit = 0, backLimit = 0; |
|
|
|
if ($scope.curDialog.messageID) { |
|
maxID = parseInt($scope.curDialog.messageID); |
|
limit = 20; |
|
backLimit = 20; |
|
} |
|
else if (forceRecent) { |
|
limit = 10; |
|
} |
|
|
|
moreActive = false; |
|
morePending = false; |
|
lessActive = false; |
|
lessPending = false; |
|
|
|
var prerenderedLen = peerHistory.messages.length; |
|
if (prerenderedLen && (maxID || backLimit)) { |
|
prerenderedLen = 0; |
|
peerHistory.messages = []; |
|
} |
|
|
|
var curJump = ++jump, |
|
inputMediaFilter = $scope.historyFilter.mediaType && {_: inputMediaFilters[$scope.historyFilter.mediaType]}, |
|
getMessagesPromise = inputMediaFilter |
|
? AppMessagesManager.getSearch($scope.curDialog.inputPeer, '', inputMediaFilter, maxID) |
|
: AppMessagesManager.getHistory($scope.curDialog.inputPeer, maxID, limit, backLimit, prerenderedLen); |
|
|
|
|
|
$scope.state.mayBeHasMore = true; |
|
getMessagesPromise.then(function (historyResult) { |
|
if (curJump != jump) return; |
|
|
|
var fetchedLength = historyResult.history.length; |
|
|
|
minID = (historyResult.unreadSkip || maxID && historyResult.history.indexOf(maxID) >= backLimit - 1) |
|
? historyResult.history[0] |
|
: 0; |
|
maxID = historyResult.history[historyResult.history.length - 1]; |
|
|
|
$scope.historyState.skipped = hasLess = minID > 0; |
|
hasMore = historyResult.count === null || |
|
fetchedLength && fetchedLength < historyResult.count; |
|
|
|
updateHistoryPeer(); |
|
safeReplaceObject($scope.state, {loaded: true, empty: !fetchedLength}); |
|
|
|
peerHistory.messages = []; |
|
angular.forEach(historyResult.history, function (id) { |
|
var message = AppMessagesManager.wrapForHistory(id); |
|
if ($scope.historyState.skipped) { |
|
delete message.unread; |
|
} |
|
if (historyResult.unreadOffset) { |
|
message.unreadAfter = true; |
|
} |
|
peerHistory.messages.push(message); |
|
}); |
|
peerHistory.messages.reverse(); |
|
|
|
if (AppMessagesManager.regroupWrappedHistory(peerHistory.messages)) { |
|
$scope.$broadcast('messages_regroup'); |
|
} |
|
|
|
if (historyResult.unreadOffset) { |
|
$scope.historyUnreadAfter = historyResult.history[historyResult.unreadOffset - 1]; |
|
} |
|
else if ($scope.historyUnreadAfter) { |
|
delete $scope.historyUnreadAfter; |
|
} |
|
$scope.$broadcast('messages_unread_after'); |
|
onContentLoaded(function () { |
|
$scope.$broadcast('messages_focus', $scope.curDialog.messageID || 0); |
|
}); |
|
$scope.$broadcast('ui_history_change'); |
|
|
|
AppMessagesManager.readHistory($scope.curDialog.inputPeer); |
|
|
|
}, function () { |
|
safeReplaceObject($scope.state, {error: true}); |
|
}); |
|
} |
|
|
|
function showEmptyHistory () { |
|
jump++; |
|
safeReplaceObject($scope.historyPeer, {}); |
|
safeReplaceObject($scope.state, {notSelected: true}); |
|
peerHistory = false; |
|
hasMore = false; |
|
|
|
$scope.$broadcast('ui_history_change'); |
|
} |
|
|
|
function toggleMessage (messageID, $event) { |
|
var target = $event.target, |
|
shiftClick = $event.shiftKey; |
|
|
|
if (shiftClick) { |
|
$scope.$broadcast('ui_selection_clear'); |
|
} |
|
|
|
if (!$scope.historyState.selectActions && !$(target).hasClass('icon-select-tick') && !$(target).hasClass('im_content_message_select_area')) { |
|
return false; |
|
} |
|
|
|
if ($scope.selectedMsgs[messageID]) { |
|
lastSelectID = false; |
|
delete $scope.selectedMsgs[messageID]; |
|
$scope.selectedCount--; |
|
if (!$scope.selectedCount) { |
|
$scope.historyState.selectActions = false; |
|
$scope.$broadcast('ui_panel_update'); |
|
} |
|
} else { |
|
|
|
if (!shiftClick) { |
|
lastSelectID = messageID; |
|
} else if (lastSelectID != messageID) { |
|
var dir = lastSelectID > messageID, |
|
i, startPos, curMessageID; |
|
|
|
for (i = 0; i < peerHistory.messages.length; i++) { |
|
if (peerHistory.messages[i].id == lastSelectID) { |
|
startPos = i; |
|
break; |
|
} |
|
} |
|
|
|
i = startPos; |
|
while (peerHistory.messages[i] && |
|
(curMessageID = peerHistory.messages[i].id) != messageID) { |
|
if (!$scope.selectedMsgs[curMessageID]) { |
|
$scope.selectedMsgs[curMessageID] = true; |
|
$scope.selectedCount++; |
|
} |
|
i += dir ? -1 : +1; |
|
} |
|
} |
|
|
|
$scope.selectedMsgs[messageID] = true; |
|
$scope.selectedCount++; |
|
if (!$scope.historyState.selectActions) { |
|
$scope.historyState.selectActions = true; |
|
$scope.$broadcast('ui_panel_update'); |
|
} |
|
} |
|
$scope.$broadcast('messages_select'); |
|
} |
|
|
|
function selectedCancel (noBroadcast) { |
|
$scope.selectedMsgs = {}; |
|
$scope.selectedCount = 0; |
|
$scope.historyState.selectActions = false; |
|
lastSelectID = false; |
|
if (!noBroadcast) { |
|
$scope.$broadcast('ui_panel_update'); |
|
} |
|
$scope.$broadcast('messages_select'); |
|
} |
|
|
|
function selectedFlush () { |
|
ErrorService.confirm({type: 'HISTORY_FLUSH'}).then(function () { |
|
AppMessagesManager.flushHistory($scope.curDialog.inputPeer).then(function () { |
|
selectedCancel(); |
|
}); |
|
}) |
|
}; |
|
|
|
function selectedDelete () { |
|
if ($scope.selectedCount > 0) { |
|
var selectedMessageIDs = []; |
|
angular.forEach($scope.selectedMsgs, function (t, messageID) { |
|
selectedMessageIDs.push(messageID); |
|
}); |
|
if (selectedMessageIDs.length) { |
|
ErrorService.confirm({type: 'MESSAGES_DELETE', count: selectedMessageIDs.length}).then(function () { |
|
AppMessagesManager.deleteMessages(selectedMessageIDs).then(function () { |
|
selectedCancel(); |
|
}); |
|
}); |
|
} |
|
} |
|
} |
|
|
|
|
|
function selectedForward () { |
|
if ($scope.selectedCount > 0) { |
|
var selectedMessageIDs = []; |
|
angular.forEach($scope.selectedMsgs, function (t, messageID) { |
|
selectedMessageIDs.push(messageID); |
|
}); |
|
|
|
PeersSelectService.selectPeers({confirm_type: 'FORWARD_PEER'}).then(function (peerStrings) { |
|
angular.forEach(peerStrings, function (peerString) { |
|
var peerID = AppPeersManager.getPeerID(peerString); |
|
AppMessagesManager.forwardMessages(peerID, selectedMessageIDs).then(function () { |
|
selectedCancel(); |
|
if (peerStrings.length == 1) { |
|
$rootScope.$broadcast('history_focus', {peerString: peerString}); |
|
} |
|
}); |
|
}); |
|
}); |
|
|
|
} |
|
} |
|
|
|
function selectedReply () { |
|
if ($scope.selectedCount == 1) { |
|
var selectedMessageID; |
|
angular.forEach($scope.selectedMsgs, function (t, messageID) { |
|
selectedMessageID = messageID; |
|
}); |
|
selectedCancel(); |
|
$scope.$broadcast('reply_selected', selectedMessageID); |
|
} |
|
} |
|
|
|
function toggleEdit () { |
|
if ($scope.historyState.selectActions) { |
|
selectedCancel(); |
|
} else { |
|
$scope.historyState.selectActions = true; |
|
$scope.$broadcast('ui_panel_update'); |
|
} |
|
} |
|
|
|
function toggleMedia (mediaType) { |
|
$scope.historyFilter.mediaType = mediaType || false; |
|
peerHistory.messages = []; |
|
$scope.state.empty = true; |
|
loadHistory(); |
|
} |
|
|
|
function returnToRecent () { |
|
if ($scope.historyFilter.mediaType) { |
|
toggleMedia(); |
|
} else { |
|
if ($scope.curDialog.messageID) { |
|
$rootScope.$broadcast('history_focus', {peerString: $scope.curDialog.peer}); |
|
} else { |
|
loadHistory(true); |
|
} |
|
} |
|
} |
|
|
|
$scope.$on('history_update', angular.noop); |
|
|
|
var typingTimeouts = {}; |
|
$scope.$on('history_append', function (e, addedMessage) { |
|
var history = historiesQueueFind(addedMessage.peerID); |
|
if (!history) { |
|
return; |
|
} |
|
var curPeer = addedMessage.peerID == $scope.curDialog.peerID; |
|
if (curPeer) { |
|
if ($scope.historyFilter.mediaType || $scope.historyState.skipped) { |
|
if (addedMessage.my) { |
|
returnToRecent(); |
|
} else { |
|
$scope.historyState.missedCount++; |
|
} |
|
return; |
|
} |
|
delete $scope.state.empty; |
|
} |
|
// console.log('append', addedMessage); |
|
// console.trace(); |
|
var historyMessage = AppMessagesManager.wrapForHistory(addedMessage.messageID); |
|
history.messages.push(historyMessage); |
|
if (AppMessagesManager.regroupWrappedHistory(history.messages, -3)) { |
|
$scope.$broadcast('messages_regroup'); |
|
} |
|
|
|
if (curPeer) { |
|
$scope.historyState.typing.splice(0, $scope.historyState.typing.length); |
|
$scope.$broadcast('ui_history_append_new', { |
|
my: addedMessage.my, |
|
idleScroll: unreadAfterIdle && !historyMessage.out && $rootScope.idle.isIDLE |
|
}); |
|
if (addedMessage.my && $scope.historyUnreadAfter) { |
|
delete $scope.historyUnreadAfter; |
|
$scope.$broadcast('messages_unread_after'); |
|
} |
|
|
|
// console.log('append check', $rootScope.idle.isIDLE, addedMessage.peerID, $scope.curDialog.peerID, historyMessage, history.messages[history.messages.length - 2]); |
|
if ($rootScope.idle.isIDLE) { |
|
if (historyMessage.unread && |
|
!historyMessage.out && |
|
!(history.messages[history.messages.length - 2] || {}).unread) { |
|
|
|
$scope.historyUnreadAfter = historyMessage.id; |
|
unreadAfterIdle = true; |
|
$scope.$broadcast('messages_unread_after'); |
|
} |
|
} else { |
|
$timeout(function () { |
|
AppMessagesManager.readHistory($scope.curDialog.inputPeer); |
|
}); |
|
} |
|
} |
|
}); |
|
|
|
$scope.$on('history_delete', function (e, historyUpdate) { |
|
var history = historiesQueueFind(historyUpdate.peerID); |
|
if (!history) { |
|
return; |
|
} |
|
var newMessages = [], |
|
i; |
|
|
|
for (i = 0; i < history.messages.length; i++) { |
|
if (!historyUpdate.msgs[history.messages[i].id]) { |
|
newMessages.push(history.messages[i]); |
|
} |
|
}; |
|
history.messages = newMessages; |
|
AppMessagesManager.regroupWrappedHistory(history.messages); |
|
$scope.$broadcast('messages_regroup'); |
|
if (historyUpdate.peerID == $scope.curDialog.peerID) { |
|
$scope.state.empty = !newMessages.length; |
|
} |
|
}); |
|
|
|
$scope.$on('dialog_flush', function (e, dialog) { |
|
var history = historiesQueueFind(dialog.peerID); |
|
if (history) { |
|
history.messages = []; |
|
if (dialog.peerID == $scope.curDialog.peerID) { |
|
$scope.state.empty = true; |
|
} |
|
} |
|
}); |
|
|
|
$scope.$on('history_focus', function (e, peerData) { |
|
if ($scope.historyFilter.mediaType) { |
|
toggleMedia(); |
|
} |
|
}); |
|
|
|
$scope.$on('apiUpdate', function (e, update) { |
|
switch (update._) { |
|
case 'updateUserTyping': |
|
case 'updateChatUserTyping': |
|
AppUsersManager.forceUserOnline(update.user_id); |
|
if (AppUsersManager.hasUser(update.user_id) && |
|
$scope.curDialog.peerID == (update._ == 'updateUserTyping' |
|
? update.user_id |
|
: -update.chat_id |
|
)) { |
|
if ($scope.historyState.typing.indexOf(update.user_id) == -1) { |
|
$scope.historyState.typing.push(update.user_id); |
|
} |
|
$timeout.cancel(typingTimeouts[update.user_id]); |
|
|
|
typingTimeouts[update.user_id] = $timeout(function () { |
|
var pos = $scope.historyState.typing.indexOf(update.user_id); |
|
if (pos !== -1) { |
|
$scope.historyState.typing.splice(pos, 1); |
|
} |
|
}, 6000); |
|
} |
|
break; |
|
} |
|
}); |
|
|
|
$scope.$on('history_need_less', showLessHistory); |
|
$scope.$on('history_need_more', showMoreHistory); |
|
|
|
$rootScope.$watch('idle.isIDLE', function (newVal) { |
|
if (!newVal && $scope.curDialog && $scope.curDialog.peerID && !$scope.historyFilter.mediaType && !$scope.historyState.skipped) { |
|
AppMessagesManager.readHistory($scope.curDialog.inputPeer); |
|
} |
|
if (!newVal) { |
|
unreadAfterIdle = false; |
|
} |
|
}); |
|
|
|
}) |
|
|
|
.controller('AppImPanelController', function($scope) { |
|
$scope.$on('user_update', angular.noop); |
|
}) |
|
|
|
.controller('AppImSendController', function ($scope, $timeout, MtpApiManager, Storage, AppChatsManager, AppUsersManager, AppPeersManager, AppDocsManager, AppMessagesManager, ApiUpdatesManager, MtpApiFileManager) { |
|
|
|
$scope.$watch('curDialog.peer', resetDraft); |
|
$scope.$on('user_update', angular.noop); |
|
$scope.$on('reply_selected', function (e, messageID) { |
|
replySelect(messageID); |
|
}); |
|
$scope.$on('ui_typing', onTyping); |
|
|
|
$scope.draftMessage = {text: '', send: sendMessage, replyClear: replyClear}; |
|
$scope.mentions = {}; |
|
$scope.$watch('draftMessage.text', onMessageChange); |
|
$scope.$watch('draftMessage.files', onFilesSelected); |
|
$scope.$watch('draftMessage.sticker', onStickerSelected); |
|
|
|
function sendMessage (e) { |
|
$scope.$broadcast('ui_message_before_send'); |
|
|
|
$timeout(function () { |
|
var text = $scope.draftMessage.text; |
|
|
|
if (angular.isString(text) && text.length > 0) { |
|
text = text.replace(/:([a-z0-9\-\+\*_]+?):/gi, function (all, shortcut) { |
|
var emojiCode = EmojiHelper.shortcuts[shortcut]; |
|
if (emojiCode !== undefined) { |
|
return EmojiHelper.emojis[emojiCode][0]; |
|
} |
|
return all; |
|
}); |
|
|
|
var timeout = 0; |
|
var options = { |
|
replyToMsgID: $scope.draftMessage.replyToMessage && $scope.draftMessage.replyToMessage.id |
|
}; |
|
do { |
|
|
|
(function (peerID, curText, curTimeout) { |
|
setTimeout(function () { |
|
AppMessagesManager.sendText(peerID, curText, options); |
|
}, curTimeout) |
|
})($scope.curDialog.peerID, text.substr(0, 4096), timeout); |
|
|
|
text = text.substr(4096); |
|
timeout += 100; |
|
|
|
} while (text.length); |
|
} |
|
|
|
resetDraft(); |
|
$scope.$broadcast('ui_message_send'); |
|
}); |
|
|
|
return cancelEvent(e); |
|
} |
|
|
|
function updateMentions () { |
|
var peerID = $scope.curDialog.peerID; |
|
|
|
if (!peerID || peerID > 0) { |
|
safeReplaceObject($scope.mentions, {}); |
|
$scope.$broadcast('mentions_update'); |
|
return; |
|
} |
|
AppChatsManager.getChatFull(-peerID).then(function (chatFull) { |
|
var participantsVector = (chatFull.participants || {}).participants || []; |
|
|
|
var mentionUsers = []; |
|
var mentionIndex = SearchIndexManager.createIndex(); |
|
|
|
angular.forEach(participantsVector, function (participant) { |
|
var user = AppUsersManager.getUser(participant.user_id); |
|
if (user.username) { |
|
mentionUsers.push(user); |
|
SearchIndexManager.indexObject(user.id, AppUsersManager.getUserSearchText(user.id), mentionIndex); |
|
} |
|
}); |
|
|
|
safeReplaceObject($scope.mentions, { |
|
users: mentionUsers, |
|
index: mentionIndex |
|
}); |
|
$scope.$broadcast('mentions_update'); |
|
}); |
|
} |
|
|
|
function resetDraft (newPeer) { |
|
updateMentions(); |
|
replyClear(); |
|
|
|
if (newPeer) { |
|
Storage.get('draft' + $scope.curDialog.peerID).then(function (draftText) { |
|
// console.log('Restore draft', 'draft' + $scope.curDialog.peerID, draftText); |
|
$scope.draftMessage.text = draftText || ''; |
|
// console.log('send broadcast', $scope.draftMessage); |
|
$scope.$broadcast('ui_peer_draft'); |
|
}); |
|
} else { |
|
// console.log('Reset peer'); |
|
$scope.draftMessage.text = ''; |
|
$scope.$broadcast('ui_peer_draft'); |
|
} |
|
} |
|
|
|
function replySelect(messageID) { |
|
$scope.draftMessage.replyToMessage = AppMessagesManager.wrapForDialog(messageID); |
|
$scope.$broadcast('ui_peer_reply'); |
|
} |
|
|
|
function replyClear() { |
|
delete $scope.draftMessage.replyToMessage; |
|
$scope.$broadcast('ui_peer_reply'); |
|
} |
|
|
|
function onMessageChange(newVal) { |
|
// console.log('ctrl text changed', newVal); |
|
// console.trace('ctrl text changed', newVal); |
|
|
|
if (newVal && newVal.length) { |
|
if (!$scope.historyFilter.mediaType && !$scope.historyState.skipped) { |
|
AppMessagesManager.readHistory($scope.curDialog.inputPeer); |
|
} |
|
|
|
var backupDraftObj = {}; |
|
backupDraftObj['draft' + $scope.curDialog.peerID] = newVal; |
|
Storage.set(backupDraftObj); |
|
// console.log(dT(), 'draft save', backupDraftObj); |
|
} else { |
|
Storage.remove('draft' + $scope.curDialog.peerID); |
|
// console.log(dT(), 'draft delete', 'draft' + $scope.curDialog.peerID); |
|
} |
|
} |
|
|
|
function onTyping () { |
|
MtpApiManager.invokeApi('messages.setTyping', { |
|
peer: $scope.curDialog.inputPeer, |
|
action: {_: 'sendMessageTypingAction'} |
|
}); |
|
} |
|
|
|
function onFilesSelected (newVal) { |
|
if (!angular.isArray(newVal) || !newVal.length) { |
|
return; |
|
} |
|
var options = { |
|
replyToMsgID: $scope.draftMessage.replyToMessage && $scope.draftMessage.replyToMessage.id, |
|
isMedia: $scope.draftMessage.isMedia |
|
}; |
|
|
|
delete $scope.draftMessage.replyToMessage; |
|
|
|
for (var i = 0; i < newVal.length; i++) { |
|
AppMessagesManager.sendFile($scope.curDialog.peerID, newVal[i], options); |
|
$scope.$broadcast('ui_message_send'); |
|
} |
|
} |
|
|
|
function onStickerSelected (newVal) { |
|
if (!newVal) { |
|
return; |
|
} |
|
|
|
var doc = AppDocsManager.getDoc(newVal); |
|
if (doc.id && doc.access_hash) { |
|
var inputMedia = { |
|
_: 'inputMediaDocument', |
|
id: { |
|
_: 'inputDocument', |
|
id: doc.id, |
|
access_hash: doc.access_hash |
|
} |
|
} |
|
AppMessagesManager.sendOther($scope.curDialog.peerID, inputMedia); |
|
$scope.$broadcast('ui_message_send'); |
|
} |
|
delete $scope.draftMessage.sticker; |
|
} |
|
}) |
|
|
|
.controller('AppLangSelectController', function ($scope, _, Storage, ErrorService, AppRuntimeManager) { |
|
$scope.supportedLocales = Config.I18n.supported; |
|
$scope.langNames = Config.I18n.languages; |
|
$scope.curLocale = Config.I18n.locale; |
|
$scope.form = {locale: Config.I18n.locale}; |
|
|
|
$scope.localeSelect = function localeSelect (newLocale) { |
|
newLocale = newLocale || $scope.form.locale; |
|
if ($scope.curLocale !== newLocale) { |
|
ErrorService.confirm({type: 'APPLY_LANG_WITH_RELOAD'}).then(function () { |
|
Storage.set({i18n_locale: newLocale}).then(function () { |
|
AppRuntimeManager.reload(); |
|
}); |
|
}, function () { |
|
$scope.form.locale = $scope.curLocale; |
|
}); |
|
} |
|
}; |
|
}) |
|
|
|
.controller('AppFooterController', function ($scope, LayoutSwitchService) { |
|
$scope.switchLayout = function (mobile) { |
|
LayoutSwitchService.switchLayout(mobile); |
|
} |
|
}) |
|
|
|
.controller('PhotoModalController', function ($q, $scope, $rootScope, $modalInstance, AppPhotosManager, AppMessagesManager, AppPeersManager, PeersSelectService, ErrorService) { |
|
|
|
$scope.photo = AppPhotosManager.wrapForFull($scope.photoID); |
|
$scope.nav = {}; |
|
|
|
$scope.download = function () { |
|
AppPhotosManager.downloadPhoto($scope.photoID); |
|
}; |
|
|
|
if (!$scope.messageID) { |
|
return; |
|
} |
|
|
|
|
|
$scope.forward = function () { |
|
var messageID = $scope.messageID; |
|
PeersSelectService.selectPeers({confirm_type: 'FORWARD_PEER'}).then(function (peerStrings) { |
|
angular.forEach(peerStrings, function (peerString) { |
|
var peerID = AppPeersManager.getPeerID(peerString); |
|
AppMessagesManager.forwardMessages(peerID, [messageID]).then(function () { |
|
if (peerStrings.length == 1) { |
|
$rootScope.$broadcast('history_focus', {peerString: peerString}); |
|
} |
|
}); |
|
}); |
|
}); |
|
}; |
|
|
|
$scope.goToMessage = function () { |
|
var messageID = $scope.messageID; |
|
var peerID = AppMessagesManager.getMessagePeer(AppMessagesManager.getMessage(messageID)); |
|
var peerString = AppPeersManager.getPeerString(peerID); |
|
$modalInstance.dismiss(); |
|
$rootScope.$broadcast('history_focus', {peerString: peerString, messageID: messageID}); |
|
}; |
|
|
|
$scope['delete'] = function () { |
|
var messageID = $scope.messageID; |
|
ErrorService.confirm({type: 'MESSAGE_DELETE'}).then(function () { |
|
AppMessagesManager.deleteMessages([messageID]); |
|
}); |
|
}; |
|
|
|
var peerID = AppMessagesManager.getMessagePeer(AppMessagesManager.getMessage($scope.messageID)), |
|
inputPeer = AppPeersManager.getInputPeerByID(peerID), |
|
inputQuery = '', |
|
inputFilter = {_: 'inputMessagesFilterPhotos'}, |
|
list = [$scope.messageID], |
|
preloaded = {}, |
|
maxID = $scope.messageID, |
|
hasMore = true; |
|
|
|
preloaded[$scope.messageID] = true; |
|
|
|
updatePrevNext(); |
|
|
|
AppMessagesManager.getSearch(inputPeer, inputQuery, inputFilter, 0, 1000).then(function (searchCachedResult) { |
|
if (searchCachedResult.history.indexOf($scope.messageID) >= 0) { |
|
list = searchCachedResult.history; |
|
maxID = list[list.length - 1]; |
|
|
|
updatePrevNext(); |
|
preloadPhotos(+1); |
|
} |
|
loadMore(); |
|
}, loadMore); |
|
|
|
|
|
var jump = 0; |
|
function movePosition (sign) { |
|
var curIndex = list.indexOf($scope.messageID), |
|
index = curIndex >= 0 ? curIndex + sign : 0, |
|
curJump = ++jump; |
|
|
|
var promise = index >= list.length ? loadMore() : $q.when(); |
|
promise.then(function () { |
|
if (curJump != jump) { |
|
return; |
|
} |
|
|
|
var messageID = list[index]; |
|
var message = AppMessagesManager.getMessage(messageID); |
|
if (!message || |
|
!message.media || |
|
!message.media.photo || |
|
!message.media.photo.id) { |
|
console.error('Invalid photo message', index, list, messageID, message); |
|
return; |
|
} |
|
|
|
$scope.messageID = messageID; |
|
$scope.photoID = message.media.photo.id; |
|
$scope.photo = AppPhotosManager.wrapForFull($scope.photoID); |
|
|
|
preloaded[$scope.messageID] = true; |
|
|
|
updatePrevNext(); |
|
|
|
if (sign > 0 && hasMore && list.indexOf(messageID) + 1 >= list.length) { |
|
loadMore(); |
|
} else { |
|
preloadPhotos(sign); |
|
} |
|
}); |
|
}; |
|
|
|
function preloadPhotos (sign) { |
|
// var preloadOffsets = sign < 0 ? [-1,-2,1,-3,2] : [1,2,-1,3,-2]; |
|
var preloadOffsets = sign < 0 ? [-1,-2] : [1,2]; |
|
var index = list.indexOf($scope.messageID); |
|
angular.forEach(preloadOffsets, function (offset) { |
|
var messageID = list[index + offset]; |
|
if (messageID !== undefined && preloaded[messageID] === undefined) { |
|
preloaded[messageID] = true; |
|
var message = AppMessagesManager.getMessage(messageID); |
|
var photoID = message.media.photo.id; |
|
AppPhotosManager.preloadPhoto(photoID); |
|
} |
|
}) |
|
} |
|
|
|
var loadingPromise = false; |
|
function loadMore () { |
|
if (loadingPromise) return loadingPromise; |
|
|
|
return loadingPromise = AppMessagesManager.getSearch(inputPeer, inputQuery, inputFilter, maxID).then(function (searchResult) { |
|
if (searchResult.history.length) { |
|
maxID = searchResult.history[searchResult.history.length - 1]; |
|
list = list.concat(searchResult.history); |
|
hasMore = list.length < searchResult.count; |
|
} else { |
|
hasMore = false; |
|
} |
|
|
|
updatePrevNext(searchResult.count); |
|
loadingPromise = false; |
|
|
|
if (searchResult.history.length) { |
|
return $q.reject(); |
|
} |
|
|
|
preloadPhotos(+1); |
|
}); |
|
}; |
|
|
|
function updatePrevNext (count) { |
|
var index = list.indexOf($scope.messageID); |
|
if (hasMore) { |
|
if (count) { |
|
$scope.count = Math.max(count, list.length); |
|
} |
|
} else { |
|
$scope.count = list.length; |
|
} |
|
$scope.pos = $scope.count - index; |
|
$scope.nav.hasNext = index > 0; |
|
$scope.nav.hasPrev = hasMore || index < list.length - 1; |
|
$scope.canForward = $scope.canDelete = $scope.messageID > 0; |
|
}; |
|
|
|
$scope.nav.next = function () { |
|
if (!$scope.nav.hasNext) { |
|
return false; |
|
} |
|
|
|
movePosition(-1); |
|
}; |
|
|
|
$scope.nav.prev = function () { |
|
if (!$scope.nav.hasPrev) { |
|
return false; |
|
} |
|
movePosition(+1); |
|
}; |
|
|
|
$scope.$on('history_delete', function (e, historyUpdate) { |
|
if (historyUpdate.peerID == peerID) { |
|
if (historyUpdate.msgs[$scope.messageID]) { |
|
if ($scope.nav.hasNext) { |
|
$scope.nav.next(); |
|
} else if ($scope.nav.hasPrev) { |
|
$scope.nav.prev(); |
|
} else { |
|
return $modalInstance.dismiss(); |
|
} |
|
} |
|
var newList = []; |
|
for (var i = 0; i < list.length; i++) { |
|
if (!historyUpdate.msgs[list[i]]) { |
|
newList.push(list[i]); |
|
} |
|
}; |
|
list = newList; |
|
} |
|
}); |
|
|
|
}) |
|
|
|
.controller('UserpicModalController', function ($q, $scope, $rootScope, $modalInstance, MtpApiManager, AppPhotosManager, AppUsersManager, AppPeersManager, AppMessagesManager, ApiUpdatesManager, PeersSelectService, ErrorService) { |
|
|
|
$scope.photo = AppPhotosManager.wrapForFull($scope.photoID); |
|
$scope.photo.thumb = { |
|
location: AppPhotosManager.choosePhotoSize($scope.photo, 0, 0).location |
|
}; |
|
|
|
$scope.nav = {}; |
|
$scope.canForward = true; |
|
|
|
var inputUser = AppUsersManager.getUserInput($scope.userID), |
|
list = [$scope.photoID], |
|
maxID = $scope.photoID, |
|
preloaded = {}, |
|
myID = 0, |
|
hasMore = true; |
|
|
|
updatePrevNext(); |
|
|
|
AppPhotosManager.getUserPhotos(inputUser, 0, 1000).then(function (userpicCachedResult) { |
|
if (userpicCachedResult.photos.indexOf($scope.photoID) >= 0) { |
|
list = userpicCachedResult.photos; |
|
maxID = list[list.length - 1]; |
|
} |
|
hasMore = list.length < userpicCachedResult.count; |
|
updatePrevNext(); |
|
}); |
|
|
|
MtpApiManager.getUserID().then(function (id) { |
|
myID = id; |
|
$scope.canDelete = $scope.photo.user_id == myID; |
|
}); |
|
|
|
|
|
var jump = 0; |
|
function movePosition (sign, deleteCurrent) { |
|
var curIndex = list.indexOf($scope.photoID), |
|
index = curIndex >= 0 ? curIndex + sign : 0, |
|
curJump = ++jump; |
|
|
|
var promise = index >= list.length ? loadMore() : $q.when(); |
|
promise.then(function () { |
|
if (curJump != jump) { |
|
return; |
|
} |
|
|
|
$scope.photoID = list[index]; |
|
$scope.photo = AppPhotosManager.wrapForFull($scope.photoID); |
|
$scope.photo.thumb = { |
|
location: AppPhotosManager.choosePhotoSize($scope.photo, 0, 0).location |
|
}; |
|
|
|
var newCount; |
|
if (deleteCurrent) { |
|
list.splice(curIndex, 1); |
|
newCount = $scope.count - 1; |
|
} |
|
|
|
updatePrevNext(newCount); |
|
|
|
preloaded[$scope.photoID] = true; |
|
|
|
updatePrevNext(); |
|
|
|
if (sign > 0 && hasMore && list.indexOf($scope.photoID) + 1 >= list.length) { |
|
loadMore(); |
|
} else { |
|
preloadPhotos(sign); |
|
} |
|
}); |
|
}; |
|
|
|
function preloadPhotos (sign) { |
|
var preloadOffsets = sign < 0 ? [-1,-2] : [1,2]; |
|
var index = list.indexOf($scope.photoID); |
|
angular.forEach(preloadOffsets, function (offset) { |
|
var photoID = list[index + offset]; |
|
if (photoID !== undefined && preloaded[photoID] === undefined) { |
|
preloaded[photoID] = true; |
|
AppPhotosManager.preloadPhoto(photoID); |
|
} |
|
}) |
|
} |
|
|
|
var loadingPromise = false; |
|
function loadMore () { |
|
if (loadingPromise) return loadingPromise; |
|
|
|
return loadingPromise = AppPhotosManager.getUserPhotos(inputUser, maxID).then(function (userpicResult) { |
|
if (userpicResult.photos.length) { |
|
maxID = userpicResult.photos[userpicResult.photos.length - 1]; |
|
list = list.concat(userpicResult.photos); |
|
|
|
hasMore = list.length < userpicResult.count; |
|
} else { |
|
hasMore = false; |
|
} |
|
|
|
updatePrevNext(userpicResult.count); |
|
loadingPromise = false; |
|
|
|
if (userpicResult.photos.length) { |
|
return $q.reject(); |
|
} |
|
|
|
preloadPhotos(+1); |
|
}); |
|
}; |
|
|
|
function updatePrevNext (count) { |
|
var index = list.indexOf($scope.photoID); |
|
if (hasMore) { |
|
if (count) { |
|
$scope.count = Math.max(count, list.length); |
|
} |
|
} else { |
|
$scope.count = list.length; |
|
} |
|
$scope.pos = $scope.count - index; |
|
$scope.nav.hasNext = index > 0; |
|
$scope.nav.hasPrev = hasMore || index < list.length - 1; |
|
$scope.canDelete = $scope.photo.user_id == myID; |
|
}; |
|
|
|
$scope.nav.next = function () { |
|
if (!$scope.nav.hasNext) { |
|
return false; |
|
} |
|
|
|
movePosition(-1); |
|
}; |
|
|
|
$scope.nav.prev = function () { |
|
if (!$scope.nav.hasPrev) { |
|
return false; |
|
} |
|
movePosition(+1); |
|
}; |
|
|
|
$scope.forward = function () { |
|
PeersSelectService.selectPeers({confirm_type: 'FORWARD_PEER'}).then(function (peerStrings) { |
|
angular.forEach(peerStrings, function (peerString) { |
|
var peerID = AppPeersManager.getPeerID(peerString); |
|
AppMessagesManager.sendOther(peerID, { |
|
_: 'inputMediaPhoto', |
|
id: { |
|
_: 'inputPhoto', |
|
id: $scope.photoID, |
|
access_hash: $scope.photo.access_hash, |
|
} |
|
}); |
|
if (peerStrings.length == 1) { |
|
$rootScope.$broadcast('history_focus', {peerString: peerStrings[0]}); |
|
} |
|
}); |
|
}); |
|
}; |
|
|
|
$scope['delete'] = function () { |
|
var photoID = $scope.photoID; |
|
var myUser = AppUsersManager.getUser(myID); |
|
var onDeleted = function () { |
|
if (!$scope.nav.hasNext && !$scope.nav.hasPrev) { |
|
return $modalInstance.dismiss(); |
|
} |
|
movePosition($scope.nav.hasNext ? -1 : +1, true); |
|
}; |
|
|
|
ErrorService.confirm({type: 'PHOTO_DELETE'}).then(function () { |
|
if (myUser && myUser.photo && myUser.photo.photo_id == photoID) { |
|
MtpApiManager.invokeApi('photos.updateProfilePhoto', { |
|
id: {_: 'inputPhotoEmpty'}, |
|
crop: {_: 'inputPhotoCropAuto'} |
|
}).then(function (updateResult) { |
|
ApiUpdatesManager.processUpdateMessage({ |
|
_: 'updateShort', |
|
update: { |
|
_: 'updateUserPhoto', |
|
user_id: myID, |
|
date: tsNow(true), |
|
photo: updateResult, |
|
previous: true |
|
} |
|
}); |
|
onDeleted(); |
|
}); |
|
} |
|
else { |
|
MtpApiManager.invokeApi('photos.deletePhotos', { |
|
id: [{_: 'inputPhoto', id: photoID, access_hash: 0}] |
|
}).then(onDeleted); |
|
} |
|
}); |
|
}; |
|
|
|
$scope.download = function () { |
|
AppPhotosManager.downloadPhoto($scope.photoID); |
|
}; |
|
|
|
}) |
|
|
|
.controller('ChatpicModalController', function ($q, $scope, $rootScope, $modalInstance, MtpApiManager, AppPhotosManager, AppChatsManager, AppPeersManager, AppMessagesManager, PeersSelectService, ErrorService) { |
|
|
|
$scope.photo = AppPhotosManager.wrapForFull($scope.photoID); |
|
$scope.photo.thumb = { |
|
location: AppPhotosManager.choosePhotoSize($scope.photo, 0, 0).location |
|
}; |
|
|
|
$scope.canForward = true; |
|
$scope.canDelete = true; |
|
|
|
$scope.forward = function () { |
|
PeersSelectService.selectPeers({confirm_type: 'FORWARD_PEER'}).then(function (peerStrings) { |
|
angular.forEach(peerStrings, function (peerString) { |
|
var peerID = AppPeersManager.getPeerID(peerString); |
|
AppMessagesManager.sendOther(peerID, { |
|
_: 'inputMediaPhoto', |
|
id: { |
|
_: 'inputPhoto', |
|
id: $scope.photoID, |
|
access_hash: $scope.photo.access_hash, |
|
} |
|
}); |
|
if (peerStrings.length == 1) { |
|
$rootScope.$broadcast('history_focus', {peerString: peerStrings[0]}); |
|
} |
|
}); |
|
}); |
|
}; |
|
|
|
$scope['delete'] = function () { |
|
ErrorService.confirm({type: 'PHOTO_DELETE'}).then(function () { |
|
$scope.photo.updating = true; |
|
MtpApiManager.invokeApi('messages.editChatPhoto', { |
|
chat_id: $scope.chatID, |
|
photo: {_: 'inputChatPhotoEmpty'} |
|
}).then(function (updateResult) { |
|
AppMessagesManager.onStatedMessage(updateResult); |
|
$modalInstance.dismiss(); |
|
$rootScope.$broadcast('history_focus', {peerString: AppChatsManager.getChatString($scope.chatID)}); |
|
})['finally'](function () { |
|
$scope.photo.updating = false; |
|
}); |
|
}); |
|
}; |
|
|
|
$scope.download = function () { |
|
AppPhotosManager.downloadPhoto($scope.photoID); |
|
}; |
|
|
|
}) |
|
|
|
.controller('VideoModalController', function ($scope, $rootScope, $modalInstance, PeersSelectService, AppMessagesManager, AppVideoManager, AppPeersManager, ErrorService) { |
|
|
|
$scope.video = AppVideoManager.wrapForFull($scope.videoID); |
|
|
|
$scope.progress = {enabled: false}; |
|
$scope.player = {}; |
|
|
|
|
|
$scope.forward = function () { |
|
var messageID = $scope.messageID; |
|
PeersSelectService.selectPeers({confirm_type: 'FORWARD_PEER'}).then(function (peerStrings) { |
|
angular.forEach(peerStrings, function (peerString) { |
|
var peerID = AppPeersManager.getPeerID(peerString); |
|
AppMessagesManager.forwardMessages(peerID, [messageID]).then(function () { |
|
if (peerStrings.length == 1) { |
|
$rootScope.$broadcast('history_focus', {peerString: peerString}); |
|
} |
|
}); |
|
}); |
|
}); |
|
}; |
|
|
|
$scope['delete'] = function () { |
|
var messageID = $scope.messageID; |
|
ErrorService.confirm({type: 'MESSAGE_DELETE'}).then(function () { |
|
AppMessagesManager.deleteMessages([messageID]); |
|
}); |
|
}; |
|
|
|
$scope.download = function () { |
|
AppVideoManager.saveVideoFile($scope.videoID); |
|
}; |
|
|
|
$scope.$on('history_delete', function (e, historyUpdate) { |
|
if (historyUpdate.msgs[$scope.messageID]) { |
|
$modalInstance.dismiss(); |
|
} |
|
}); |
|
}) |
|
|
|
.controller('DocumentModalController', function ($scope, $rootScope, $modalInstance, PeersSelectService, AppMessagesManager, AppDocsManager, AppPeersManager, ErrorService) { |
|
|
|
$scope.document = AppDocsManager.wrapForHistory($scope.docID); |
|
|
|
$scope.forward = function () { |
|
var messageID = $scope.messageID; |
|
PeersSelectService.selectPeers({confirm_type: 'FORWARD_PEER'}).then(function (peerStrings) { |
|
angular.forEach(peerStrings, function (peerString) { |
|
var peerID = AppPeersManager.getPeerID(peerString); |
|
AppMessagesManager.forwardMessages(peerID, [messageID]).then(function () { |
|
if (peerStrings.length == 1) { |
|
$rootScope.$broadcast('history_focus', {peerString: peerString}); |
|
} |
|
}); |
|
}); |
|
}); |
|
}; |
|
|
|
$scope['delete'] = function () { |
|
var messageID = $scope.messageID; |
|
ErrorService.confirm({type: 'MESSAGE_DELETE'}).then(function () { |
|
AppMessagesManager.deleteMessages([messageID]); |
|
}); |
|
}; |
|
|
|
$scope.download = function () { |
|
AppDocsManager.saveDocFile($scope.docID); |
|
}; |
|
|
|
$scope.$on('history_delete', function (e, historyUpdate) { |
|
if (historyUpdate.msgs[$scope.messageID]) { |
|
$modalInstance.dismiss(); |
|
} |
|
}); |
|
}) |
|
|
|
.controller('UserModalController', function ($scope, $location, $rootScope, $modal, AppUsersManager, MtpApiManager, NotificationsManager, AppPhotosManager, AppMessagesManager, AppPeersManager, PeersSelectService, ErrorService) { |
|
|
|
var peerString = AppUsersManager.getUserString($scope.userID); |
|
|
|
$scope.user = AppUsersManager.getUser($scope.userID); |
|
$scope.userPhoto = AppUsersManager.getUserPhoto($scope.userID, 'User'); |
|
$scope.blocked = false; |
|
|
|
$scope.settings = {notifications: true}; |
|
|
|
MtpApiManager.invokeApi('users.getFullUser', { |
|
id: AppUsersManager.getUserInput($scope.userID) |
|
}).then(function (userFullResult) { |
|
if ($scope.override && $scope.override.phone_number) { |
|
userFullResult.user.phone = $scope.override.phone_number; |
|
if ($scope.override.first_name || $scope.override.last_name) { |
|
userFullResult.user.first_name = $scope.override.first_name; |
|
userFullResult.user.last_name = $scope.override.last_name; |
|
} |
|
AppUsersManager.saveApiUser(userFullResult.user); |
|
} else { |
|
AppUsersManager.saveApiUser(userFullResult.user, true); |
|
} |
|
AppPhotosManager.savePhoto(userFullResult.profile_photo); |
|
$scope.blocked = userFullResult.blocked; |
|
|
|
NotificationsManager.savePeerSettings($scope.userID, userFullResult.notify_settings); |
|
NotificationsManager.getPeerMuted($scope.userID).then(function (muted) { |
|
$scope.settings.notifications = !muted; |
|
|
|
$scope.$watch('settings.notifications', function(newValue, oldValue) { |
|
if (newValue === oldValue) { |
|
return false; |
|
} |
|
NotificationsManager.getPeerSettings($scope.userID).then(function (settings) { |
|
if (newValue) { |
|
settings.mute_until = 0; |
|
} else { |
|
settings.mute_until = 2000000000; |
|
} |
|
NotificationsManager.updatePeerSettings($scope.userID, settings); |
|
}); |
|
}); |
|
}); |
|
}); |
|
|
|
|
|
$scope.goToHistory = function () { |
|
$rootScope.$broadcast('history_focus', {peerString: peerString}); |
|
}; |
|
|
|
$scope.flushHistory = function () { |
|
ErrorService.confirm({type: 'HISTORY_FLUSH'}).then(function () { |
|
AppMessagesManager.flushHistory(AppPeersManager.getInputPeerByID($scope.userID)).then(function () { |
|
$scope.goToHistory(); |
|
}); |
|
}); |
|
}; |
|
|
|
$scope.importContact = function (edit) { |
|
var scope = $rootScope.$new(); |
|
scope.importContact = { |
|
phone: $scope.user.phone, |
|
first_name: $scope.user.first_name, |
|
last_name: $scope.user.last_name, |
|
}; |
|
|
|
$modal.open({ |
|
templateUrl: templateUrl(edit ? 'edit_contact_modal' : 'import_contact_modal'), |
|
controller: 'ImportContactModalController', |
|
windowClass: 'md_simple_modal_window mobile_modal', |
|
scope: scope |
|
}).result.then(function (foundUserID) { |
|
if ($scope.userID == foundUserID) { |
|
$scope.user = AppUsersManager.getUser($scope.userID); |
|
} |
|
}); |
|
}; |
|
|
|
$scope.deleteContact = function () { |
|
AppUsersManager.deleteContacts([$scope.userID]).then(function () { |
|
$scope.user = AppUsersManager.getUser($scope.userID); |
|
}); |
|
}; |
|
|
|
$scope.toggleBlock = function (block) { |
|
MtpApiManager.invokeApi(block ? 'contacts.block' : 'contacts.unblock', { |
|
id: AppUsersManager.getUserInput($scope.userID) |
|
}).then(function () { |
|
$scope.blocked = block; |
|
}); |
|
}; |
|
|
|
$scope.shareContact = function () { |
|
PeersSelectService.selectPeers({confirm_type: 'SHARE_CONTACT_PEER'}).then(function (peerStrings) { |
|
angular.forEach(peerStrings, function (peerString) { |
|
var peerID = AppPeersManager.getPeerID(peerString); |
|
AppMessagesManager.sendOther(peerID, { |
|
_: 'inputMediaContact', |
|
phone_number: $scope.user.phone, |
|
first_name: $scope.user.first_name, |
|
last_name: $scope.user.last_name, |
|
user_id: $scope.user.id |
|
}); |
|
if (peerStrings.length == 1) { |
|
$rootScope.$broadcast('history_focus', {peerString: peerStrings[0]}); |
|
} |
|
}); |
|
}); |
|
} |
|
|
|
}) |
|
|
|
.controller('ChatModalController', 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.getChatFull($scope.chatID).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 onStatedMessage (statedMessage) { |
|
AppMessagesManager.onStatedMessage(statedMessage); |
|
$rootScope.$broadcast('history_focus', {peerString: $scope.chatFull.peerString}); |
|
} |
|
|
|
|
|
$scope.leaveGroup = function () { |
|
MtpApiManager.invokeApi('messages.deleteChatUser', { |
|
chat_id: $scope.chatID, |
|
user_id: {_: 'inputUserSelf'} |
|
}).then(onStatedMessage); |
|
}; |
|
|
|
$scope.returnToGroup = function () { |
|
MtpApiManager.invokeApi('messages.addChatUser', { |
|
chat_id: $scope.chatID, |
|
user_id: {_: 'inputUserSelf'} |
|
}).then(onStatedMessage); |
|
}; |
|
|
|
|
|
$scope.inviteToGroup = function () { |
|
var disabled = []; |
|
angular.forEach($scope.chatFull.participants.participants, function(participant){ |
|
disabled.push(participant.user_id); |
|
}); |
|
|
|
ContactsSelectService.selectContacts({disabled: disabled}).then(function (userIDs) { |
|
angular.forEach(userIDs, function (userID) { |
|
MtpApiManager.invokeApi('messages.addChatUser', { |
|
chat_id: $scope.chatID, |
|
user_id: AppUsersManager.getUserInput(userID), |
|
fwd_limit: 100 |
|
}).then(function (addResult) { |
|
ApiUpdatesManager.processUpdateMessage({ |
|
_: 'updates', |
|
users: addResult.users, |
|
chats: addResult.chats, |
|
seq: 0, |
|
updates: [{ |
|
_: 'updateNewMessage', |
|
message: addResult.message, |
|
pts: addResult.pts, |
|
pts_count: addResult.pts_count |
|
}] |
|
}); |
|
}); |
|
}); |
|
|
|
$rootScope.$broadcast('history_focus', {peerString: $scope.chatFull.peerString}); |
|
}); |
|
}; |
|
|
|
$scope.kickFromGroup = function (userID) { |
|
var user = AppUsersManager.getUser(userID); |
|
|
|
MtpApiManager.invokeApi('messages.deleteChatUser', { |
|
chat_id: $scope.chatID, |
|
user_id: {_: 'inputUserForeign', user_id: userID, access_hash: user.access_hash || '0'} |
|
}).then(onStatedMessage); |
|
}; |
|
|
|
|
|
|
|
$scope.flushHistory = function () { |
|
ErrorService.confirm({type: 'HISTORY_FLUSH'}).then(function () { |
|
AppMessagesManager.flushHistory(AppPeersManager.getInputPeerByID(-$scope.chatID)).then(function () { |
|
$rootScope.$broadcast('history_focus', {peerString: $scope.chatFull.peerString}); |
|
}); |
|
}); |
|
}; |
|
|
|
|
|
$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('messages.editChatPhoto', { |
|
chat_id: $scope.chatID, |
|
photo: { |
|
_: 'inputChatUploadedPhoto', |
|
file: inputFile, |
|
crop: {_: 'inputPhotoCropAuto'} |
|
} |
|
}).then(function (updateResult) { |
|
onStatedMessage(updateResult); |
|
}); |
|
})['finally'](function () { |
|
$scope.photo.updating = false; |
|
}); |
|
}; |
|
|
|
$scope.deletePhoto = function () { |
|
$scope.photo.updating = true; |
|
MtpApiManager.invokeApi('messages.editChatPhoto', { |
|
chat_id: $scope.chatID, |
|
photo: {_: 'inputChatPhotoEmpty'} |
|
}).then(function (updateResult) { |
|
onStatedMessage(updateResult); |
|
})['finally'](function () { |
|
$scope.photo.updating = false; |
|
}); |
|
}; |
|
|
|
$scope.editTitle = function () { |
|
var scope = $rootScope.$new(); |
|
scope.chatID = $scope.chatID; |
|
|
|
$modal.open({ |
|
templateUrl: templateUrl('chat_edit_modal'), |
|
controller: 'ChatEditModalController', |
|
scope: scope, |
|
windowClass: 'md_simple_modal_window mobile_modal' |
|
}); |
|
} |
|
|
|
}) |
|
|
|
.controller('SettingsModalController', function ($rootScope, $scope, $timeout, $modal, AppUsersManager, AppChatsManager, AppPhotosManager, MtpApiManager, Storage, NotificationsManager, MtpApiFileManager, ApiUpdatesManager, ChangelogNotifyService, LayoutSwitchService, AppRuntimeManager, ErrorService, _) { |
|
|
|
$scope.profile = {}; |
|
$scope.photo = {}; |
|
$scope.version = Config.App.version; |
|
|
|
MtpApiManager.getUserID().then(function (id) { |
|
$scope.profile = AppUsersManager.getUser(id); |
|
$scope.photo = AppUsersManager.getUserPhoto(id, 'User'); |
|
}); |
|
|
|
MtpApiManager.invokeApi('users.getFullUser', { |
|
id: {_: 'inputUserSelf'} |
|
}).then(function (userFullResult) { |
|
AppUsersManager.saveApiUser(userFullResult.user); |
|
AppPhotosManager.savePhoto(userFullResult.profile_photo); |
|
}); |
|
|
|
$scope.notify = {volume: 0.5}; |
|
$scope.send = {}; |
|
|
|
$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) { |
|
MtpApiManager.invokeApi('photos.uploadProfilePhoto', { |
|
file: inputFile, |
|
caption: '', |
|
geo_point: {_: 'inputGeoPointEmpty'}, |
|
crop: {_: 'inputPhotoCropAuto'} |
|
}).then(function (updateResult) { |
|
AppUsersManager.saveApiUsers(updateResult.users); |
|
AppPhotosManager.savePhoto(updateResult.photo); |
|
MtpApiManager.getUserID().then(function (id) { |
|
ApiUpdatesManager.processUpdateMessage({ |
|
_: 'updateShort', |
|
update: { |
|
_: 'updateUserPhoto', |
|
user_id: id, |
|
date: tsNow(true), |
|
photo: AppUsersManager.getUser(id).photo, |
|
previous: true |
|
} |
|
}); |
|
$scope.photo = AppUsersManager.getUserPhoto(id, 'User'); |
|
}); |
|
}); |
|
})['finally'](function () { |
|
delete $scope.photo.updating; |
|
}); |
|
}; |
|
|
|
$scope.deletePhoto = function () { |
|
$scope.photo.updating = true; |
|
MtpApiManager.invokeApi('photos.updateProfilePhoto', { |
|
id: {_: 'inputPhotoEmpty'}, |
|
crop: {_: 'inputPhotoCropAuto'} |
|
}).then(function (updateResult) { |
|
MtpApiManager.getUserID().then(function (id) { |
|
ApiUpdatesManager.processUpdateMessage({ |
|
_: 'updateShort', |
|
update: { |
|
_: 'updateUserPhoto', |
|
user_id: id, |
|
date: tsNow(true), |
|
photo: updateResult, |
|
previous: true |
|
} |
|
}); |
|
$scope.photo = AppUsersManager.getUserPhoto(id, 'User'); |
|
}); |
|
})['finally'](function () { |
|
delete $scope.photo.updating; |
|
}); |
|
}; |
|
|
|
$scope.editProfile = function () { |
|
$modal.open({ |
|
templateUrl: templateUrl('profile_edit_modal'), |
|
controller: 'ProfileEditModalController', |
|
windowClass: 'md_simple_modal_window mobile_modal' |
|
}); |
|
}; |
|
|
|
$scope.changeUsername = function () { |
|
$modal.open({ |
|
templateUrl: templateUrl('username_edit_modal'), |
|
controller: 'UsernameEditModalController', |
|
windowClass: 'md_simple_modal_window mobile_modal' |
|
}); |
|
}; |
|
|
|
$scope.terminateSessions = function () { |
|
ErrorService.confirm({type: 'TERMINATE_SESSIONS'}).then(function () { |
|
MtpApiManager.invokeApi('auth.resetAuthorizations', {}); |
|
}); |
|
}; |
|
|
|
Storage.get('notify_nodesktop', 'notify_nosound', 'send_ctrlenter', 'notify_volume', 'notify_novibrate', 'notify_nopreview').then(function (settings) { |
|
$scope.notify.desktop = !settings[0]; |
|
$scope.send.enter = settings[2] ? '' : '1'; |
|
|
|
if (settings[1]) { |
|
$scope.notify.volume = 0; |
|
} else if (settings[3] !== false) { |
|
$scope.notify.volume = settings[3] > 0 && settings[3] <= 1.0 ? settings[3] : 0; |
|
} else { |
|
$scope.notify.volume = 0.5; |
|
} |
|
|
|
$scope.notify.canVibrate = NotificationsManager.getVibrateSupport(); |
|
$scope.notify.vibrate = !settings[4]; |
|
|
|
$scope.notify.preview = !settings[5]; |
|
|
|
$scope.notify.volumeOf4 = function () { |
|
return 1 + Math.ceil(($scope.notify.volume - 0.1) / 0.33); |
|
}; |
|
|
|
$scope.toggleSound = function () { |
|
if ($scope.notify.volume) { |
|
$scope.notify.volume = 0; |
|
} else { |
|
$scope.notify.volume = 0.5; |
|
} |
|
} |
|
|
|
var testSoundPromise; |
|
$scope.$watch('notify.volume', function (newValue, oldValue) { |
|
if (newValue !== oldValue) { |
|
Storage.set({notify_volume: newValue}); |
|
Storage.remove('notify_nosound'); |
|
NotificationsManager.clear(); |
|
|
|
if (testSoundPromise) { |
|
$timeout.cancel(testSoundPromise); |
|
} |
|
testSoundPromise = $timeout(function () { |
|
NotificationsManager.testSound(newValue); |
|
}, 500); |
|
} |
|
}); |
|
|
|
$scope.toggleDesktop = function () { |
|
$scope.notify.desktop = !$scope.notify.desktop; |
|
|
|
if ($scope.notify.desktop) { |
|
Storage.remove('notify_nodesktop'); |
|
} else { |
|
Storage.set({notify_nodesktop: true}); |
|
} |
|
} |
|
|
|
$scope.togglePreview = function () { |
|
$scope.notify.preview = !$scope.notify.preview; |
|
|
|
if ($scope.notify.preview) { |
|
Storage.remove('notify_nopreview'); |
|
} else { |
|
Storage.set({notify_nopreview: true}); |
|
} |
|
} |
|
|
|
$scope.toggleVibrate = function () { |
|
$scope.notify.vibrate = !$scope.notify.vibrate; |
|
|
|
if ($scope.notify.vibrate) { |
|
Storage.remove('notify_novibrate'); |
|
} else { |
|
Storage.set({notify_novibrate: true}); |
|
} |
|
} |
|
|
|
$scope.toggleCtrlEnter = function (newValue) { |
|
$scope.send.enter = newValue; |
|
|
|
if ($scope.send.enter) { |
|
Storage.remove('send_ctrlenter'); |
|
} else { |
|
Storage.set({send_ctrlenter: true}); |
|
} |
|
$rootScope.$broadcast('settings_changed'); |
|
} |
|
}); |
|
|
|
$scope.openChangelog = function () { |
|
ChangelogNotifyService.showChangelog(false); |
|
}; |
|
|
|
$scope.logOut = function () { |
|
ErrorService.confirm({type: 'LOGOUT'}).then(function () { |
|
MtpApiManager.logOut().then(function () { |
|
location.hash = '/login'; |
|
AppRuntimeManager.reload(); |
|
}); |
|
}) |
|
}; |
|
|
|
$scope.switchBackToDesktop = Config.Mobile && !Config.Navigator.mobile; |
|
$scope.switchToDesktop = function () { |
|
LayoutSwitchService.switchLayout(false); |
|
}; |
|
}) |
|
|
|
.controller('ChangelogModalController', function ($scope, $modal) { |
|
|
|
$scope.currentVersion = Config.App.version; |
|
if (!$scope.lastVersion) { |
|
var versionParts = $scope.currentVersion.split('.'); |
|
$scope.lastVersion = versionParts[0] + '.' + versionParts[1] + '.' + Math.max(0, versionParts[2] - 1); |
|
} |
|
|
|
$scope.changelogHidden = false; |
|
$scope.changelogShown = false; |
|
|
|
$scope.canShowVersion = function (curVersion) { |
|
if ($scope.changelogShown) { |
|
return true; |
|
} |
|
|
|
var show = versionCompare(curVersion, $scope.lastVersion) >= 0; |
|
if (!show) { |
|
$scope.changelogHidden = true; |
|
} |
|
|
|
return show; |
|
}; |
|
|
|
$scope.showAllVersions = function () { |
|
$scope.changelogShown = true; |
|
$scope.changelogHidden = false; |
|
$scope.$emit('ui_height'); |
|
$scope.$broadcast('ui_height'); |
|
}; |
|
|
|
$scope.changeUsername = function () { |
|
$modal.open({ |
|
templateUrl: templateUrl('username_edit_modal'), |
|
controller: 'UsernameEditModalController', |
|
windowClass: 'md_simple_modal_window mobile_modal' |
|
}); |
|
}; |
|
}) |
|
|
|
.controller('ProfileEditModalController', function ($scope, $modalInstance, AppUsersManager, MtpApiManager) { |
|
|
|
$scope.profile = {}; |
|
$scope.error = {}; |
|
|
|
MtpApiManager.getUserID().then(function (id) { |
|
$scope.profile = AppUsersManager.getUser(id); |
|
}); |
|
|
|
$scope.updateProfile = function () { |
|
$scope.profile.updating = true; |
|
|
|
MtpApiManager.invokeApi('account.updateProfile', { |
|
first_name: $scope.profile.first_name || '', |
|
last_name: $scope.profile.last_name || '' |
|
}).then(function (user) { |
|
$scope.error = {}; |
|
AppUsersManager.saveApiUser(user); |
|
$modalInstance.close(); |
|
}, function (error) { |
|
switch (error.type) { |
|
case 'FIRSTNAME_INVALID': |
|
$scope.error = {field: 'first_name'}; |
|
error.handled = true; |
|
break; |
|
|
|
case 'LASTNAME_INVALID': |
|
$scope.error = {field: 'last_name'}; |
|
error.handled = true; |
|
break; |
|
|
|
case 'NAME_NOT_MODIFIED': |
|
error.handled = true; |
|
$modalInstance.close(); |
|
break; |
|
} |
|
})['finally'](function () { |
|
delete $scope.profile.updating; |
|
}); |
|
} |
|
}) |
|
|
|
.controller('UsernameEditModalController', function ($scope, $modalInstance, AppUsersManager, MtpApiManager) { |
|
|
|
$scope.profile = {}; |
|
$scope.error = {}; |
|
|
|
MtpApiManager.getUserID().then(function (id) { |
|
$scope.profile = angular.copy(AppUsersManager.getUser(id)); |
|
}); |
|
|
|
$scope.updateUsername = function () { |
|
$scope.profile.updating = true; |
|
|
|
MtpApiManager.invokeApi('account.updateUsername', { |
|
username: $scope.profile.username || '' |
|
}).then(function (user) { |
|
$scope.checked = {}; |
|
AppUsersManager.saveApiUser(user); |
|
$modalInstance.close(); |
|
}, function (error) { |
|
if (error.type == 'USERNAME_NOT_MODIFIED') { |
|
error.handled = true; |
|
$modalInstance.close(); |
|
} |
|
})['finally'](function () { |
|
delete $scope.profile.updating; |
|
}); |
|
} |
|
|
|
$scope.$watch('profile.username', function (newVal) { |
|
if (!newVal.length) { |
|
$scope.checked = {}; |
|
return; |
|
} |
|
MtpApiManager.invokeApi('account.checkUsername', { |
|
username: newVal || '' |
|
}).then(function (valid) { |
|
if ($scope.profile.username != newVal) { |
|
return; |
|
} |
|
if (valid) { |
|
$scope.checked = {success: true}; |
|
} else { |
|
$scope.checked = {error: true}; |
|
} |
|
}, function (error) { |
|
if ($scope.profile.username != newVal) { |
|
return; |
|
} |
|
switch (error.type) { |
|
case 'USERNAME_INVALID': |
|
$scope.checked = {error: true}; |
|
error.handled = true; |
|
break; |
|
} |
|
}); |
|
}) |
|
}) |
|
|
|
.controller('ContactsModalController', function ($scope, $timeout, $modal, $modalInstance, MtpApiManager, AppUsersManager, ErrorService) { |
|
|
|
$scope.contacts = []; |
|
$scope.foundUsers = []; |
|
$scope.search = {}; |
|
$scope.slice = {limit: 20, limitDelta: 20}; |
|
|
|
var jump = 0; |
|
|
|
resetSelected(); |
|
$scope.disabledContacts = {}; |
|
|
|
if ($scope.disabled) { |
|
for (var i = 0; i < $scope.disabled.length; i++) { |
|
$scope.disabledContacts[$scope.disabled[i]] = true; |
|
} |
|
} |
|
|
|
if ($scope.selected) { |
|
for (var i = 0; i < $scope.selected.length; i++) { |
|
if (!$scope.selectedContacts[$scope.selected[i]]) { |
|
$scope.selectedContacts[$scope.selected[i]] = true; |
|
$scope.selectedCount++; |
|
} |
|
} |
|
} |
|
|
|
function resetSelected () { |
|
$scope.selectedContacts = {}; |
|
$scope.selectedCount = 0; |
|
}; |
|
|
|
function updateContacts (query) { |
|
var curJump = ++jump; |
|
var doneIDs = []; |
|
AppUsersManager.getContacts(query).then(function (contactsList) { |
|
if (curJump != jump) return; |
|
$scope.contacts = []; |
|
$scope.slice.limit = 20; |
|
|
|
angular.forEach(contactsList, function(userID) { |
|
var contact = { |
|
userID: userID, |
|
user: AppUsersManager.getUser(userID), |
|
userPhoto: AppUsersManager.getUserPhoto(userID, 'User') |
|
} |
|
doneIDs.push(userID); |
|
$scope.contacts.push(contact); |
|
}); |
|
$scope.contactsEmpty = query ? false : !$scope.contacts.length; |
|
$scope.$broadcast('contacts_change'); |
|
}); |
|
|
|
if (query && query.length >= 5) { |
|
$timeout(function() { |
|
if (curJump != jump) return; |
|
MtpApiManager.invokeApi('contacts.search', {q: query, limit: 10}).then(function (result) { |
|
AppUsersManager.saveApiUsers(result.users); |
|
if (curJump != jump) return; |
|
angular.forEach(result.results, function(contactFound) { |
|
var userID = contactFound.user_id; |
|
if (doneIDs.indexOf(userID) != -1) return; |
|
$scope.contacts.push({ |
|
userID: userID, |
|
user: AppUsersManager.getUser(userID), |
|
peerString: AppUsersManager.getUserString(userID), |
|
found: true |
|
}); |
|
}); |
|
}, function (error) { |
|
if (error.code == 400) { |
|
error.handled = true; |
|
} |
|
}); |
|
}, 500); |
|
} |
|
}; |
|
|
|
$scope.$watch('search.query', updateContacts); |
|
$scope.$on('contacts_update', function () { |
|
updateContacts($scope.search && $scope.search.query || ''); |
|
}); |
|
|
|
$scope.toggleEdit = function (enabled) { |
|
$scope.action = enabled ? 'edit' : ''; |
|
$scope.multiSelect = enabled; |
|
resetSelected(); |
|
}; |
|
|
|
$scope.contactSelect = function (userID) { |
|
if ($scope.disabledContacts[userID]) { |
|
return false; |
|
} |
|
if (!$scope.multiSelect) { |
|
return $modalInstance.close(userID); |
|
} |
|
if ($scope.selectedContacts[userID]) { |
|
delete $scope.selectedContacts[userID]; |
|
$scope.selectedCount--; |
|
} else { |
|
$scope.selectedContacts[userID] = true; |
|
$scope.selectedCount++; |
|
} |
|
}; |
|
|
|
$scope.submitSelected = function () { |
|
if ($scope.selectedCount > 0) { |
|
var selectedUserIDs = []; |
|
angular.forEach($scope.selectedContacts, function (t, userID) { |
|
selectedUserIDs.push(userID); |
|
}); |
|
return $modalInstance.close(selectedUserIDs); |
|
} |
|
}; |
|
|
|
$scope.deleteSelected = function () { |
|
if ($scope.selectedCount > 0) { |
|
var selectedUserIDs = []; |
|
angular.forEach($scope.selectedContacts, function (t, userID) { |
|
selectedUserIDs.push(userID); |
|
}); |
|
AppUsersManager.deleteContacts(selectedUserIDs).then(function () { |
|
$scope.toggleEdit(false); |
|
}); |
|
} |
|
}; |
|
|
|
$scope.importContact = function () { |
|
AppUsersManager.openImportContact(); |
|
}; |
|
|
|
}) |
|
|
|
.controller('PeerSelectController', function ($scope, $modalInstance, $q, AppPeersManager, ErrorService) { |
|
|
|
$scope.selectedPeers = {}; |
|
$scope.selectedPeerIDs = []; |
|
$scope.selectedCount = 0; |
|
|
|
$scope.dialogSelect = function (peerString) { |
|
if (!$scope.multiSelect) { |
|
var promise; |
|
if ($scope.confirm_type) { |
|
var peerID = AppPeersManager.getPeerID(peerString), |
|
peerData = AppPeersManager.getPeer(peerID); |
|
promise = ErrorService.confirm({ |
|
type: $scope.confirm_type, |
|
peer_id: peerID, |
|
peer_data: peerData |
|
}); |
|
} else { |
|
promise = $q.when(); |
|
} |
|
promise.then(function () { |
|
$modalInstance.close(peerString); |
|
}); |
|
return; |
|
} |
|
|
|
var peerID = AppPeersManager.getPeerID(peerString); |
|
if ($scope.selectedPeers[peerID]) { |
|
delete $scope.selectedPeers[peerID]; |
|
$scope.selectedCount--; |
|
var pos = $scope.selectedPeerIDs.indexOf(peerID); |
|
if (pos >= 0) { |
|
$scope.selectedPeerIDs.splice(pos, 1); |
|
} |
|
} else { |
|
$scope.selectedPeers[peerID] = AppPeersManager.getPeer(peerID); |
|
$scope.selectedCount++; |
|
$scope.selectedPeerIDs.unshift(peerID); |
|
} |
|
}; |
|
|
|
$scope.submitSelected = function () { |
|
if ($scope.selectedCount > 0) { |
|
var selectedPeerStrings = []; |
|
angular.forEach($scope.selectedPeers, function (t, peerID) { |
|
selectedPeerStrings.push(AppPeersManager.getPeerString(peerID)); |
|
}); |
|
return $modalInstance.close(selectedPeerStrings); |
|
} |
|
}; |
|
|
|
$scope.toggleSearch = function () { |
|
$scope.$broadcast('dialogs_search_toggle'); |
|
}; |
|
}) |
|
|
|
.controller('ChatCreateModalController', function ($scope, $modalInstance, $rootScope, MtpApiManager, AppUsersManager, AppChatsManager, ApiUpdatesManager) { |
|
$scope.group = {name: ''}; |
|
|
|
$scope.createGroup = function () { |
|
if (!$scope.group.name) { |
|
return; |
|
} |
|
$scope.group.creating = true; |
|
var inputUsers = []; |
|
angular.forEach($scope.userIDs, function(userID) { |
|
inputUsers.push(AppUsersManager.getUserInput(userID)); |
|
}); |
|
return MtpApiManager.invokeApi('messages.createChat', { |
|
title: $scope.group.name, |
|
users: inputUsers |
|
}).then(function (createdResult) { |
|
ApiUpdatesManager.processUpdateMessage({ |
|
_: 'updates', |
|
users: createdResult.users, |
|
chats: createdResult.chats, |
|
seq: 0, |
|
updates: [{ |
|
_: 'updateNewMessage', |
|
message: createdResult.message, |
|
pts: createdResult.pts, |
|
pts_count: createdResult.pts_count |
|
}] |
|
}); |
|
|
|
var peerString = AppChatsManager.getChatString(createdResult.message.to_id.chat_id); |
|
$rootScope.$broadcast('history_focus', {peerString: peerString}); |
|
})['finally'](function () { |
|
delete $scope.group.creating; |
|
}); |
|
}; |
|
|
|
}) |
|
|
|
.controller('ChatEditModalController', function ($scope, $modalInstance, $rootScope, MtpApiManager, AppUsersManager, AppChatsManager, ApiUpdatesManager) { |
|
|
|
var chat = AppChatsManager.getChat($scope.chatID); |
|
$scope.group = {name: chat.title}; |
|
|
|
$scope.updateGroup = function () { |
|
if (!$scope.group.name) { |
|
return; |
|
} |
|
if ($scope.group.name == chat.title) { |
|
return $modalInstance.close(); |
|
} |
|
|
|
$scope.group.updating = true; |
|
|
|
return MtpApiManager.invokeApi('messages.editChatTitle', { |
|
chat_id: $scope.chatID, |
|
title: $scope.group.name |
|
}).then(function (editResult) { |
|
ApiUpdatesManager.processUpdateMessage({ |
|
_: 'updates', |
|
users: editResult.users, |
|
chats: editResult.chats, |
|
seq: 0, |
|
updates: [{ |
|
_: 'updateNewMessage', |
|
message: editResult.message, |
|
pts: editResult.pts, |
|
pts_count: editResult.pts_count |
|
}] |
|
}); |
|
|
|
var peerString = AppChatsManager.getChatString($scope.chatID); |
|
$rootScope.$broadcast('history_focus', {peerString: peerString}); |
|
})['finally'](function () { |
|
delete $scope.group.updating; |
|
}); |
|
}; |
|
}) |
|
|
|
.controller('ImportContactModalController', function ($scope, $modalInstance, $rootScope, AppUsersManager, ErrorService, PhonebookContactsService) { |
|
if ($scope.importContact === undefined) { |
|
$scope.importContact = {}; |
|
} |
|
|
|
$scope.phonebookAvailable = PhonebookContactsService.isAvailable(); |
|
|
|
$scope.doImport = function () { |
|
if ($scope.importContact && $scope.importContact.phone) { |
|
$scope.progress = {enabled: true}; |
|
AppUsersManager.importContact( |
|
$scope.importContact.phone, |
|
$scope.importContact.first_name || '', |
|
$scope.importContact.last_name || '' |
|
).then(function (foundUserID) { |
|
if (!foundUserID) { |
|
ErrorService.show({ |
|
error: {code: 404, type: 'USER_NOT_USING_TELEGRAM'} |
|
}); |
|
} |
|
$modalInstance.close(foundUserID); |
|
})['finally'](function () { |
|
delete $scope.progress.enabled; |
|
}); |
|
} |
|
}; |
|
|
|
$scope.importPhonebook = function () { |
|
PhonebookContactsService.openPhonebookImport().result.then(function (foundContacts) { |
|
if (foundContacts) { |
|
$modalInstance.close(foundContacts[0]); |
|
} else { |
|
$modalInstance.dismiss(); |
|
} |
|
}) |
|
}; |
|
|
|
}) |
|
|
|
.controller('CountrySelectModalController', function ($scope, $modalInstance, $rootScope, _) { |
|
|
|
$scope.search = {}; |
|
$scope.slice = {limit: 20, limitDelta: 20} |
|
|
|
var searchIndex = SearchIndexManager.createIndex(); |
|
|
|
for (var i = 0; i < Config.CountryCodes.length; i++) { |
|
var searchString = Config.CountryCodes[i][0]; |
|
searchString += ' ' + _(Config.CountryCodes[i][1] + '_raw'); |
|
searchString += ' ' + Config.CountryCodes[i].slice(2).join(' '); |
|
SearchIndexManager.indexObject(i, searchString, searchIndex); |
|
} |
|
|
|
$scope.$watch('search.query', function (newValue) { |
|
var filtered = false, |
|
results = {}; |
|
|
|
if (angular.isString(newValue) && newValue.length) { |
|
filtered = true; |
|
results = SearchIndexManager.search(newValue, searchIndex); |
|
} |
|
|
|
$scope.countries = []; |
|
$scope.slice.limit = 20; |
|
|
|
var j; |
|
for (var i = 0; i < Config.CountryCodes.length; i++) { |
|
if (!filtered || results[i]) { |
|
for (j = 2; j < Config.CountryCodes[i].length; j++) { |
|
$scope.countries.push({name: _(Config.CountryCodes[i][1] + '_raw'), code: Config.CountryCodes[i][j]}); |
|
} |
|
} |
|
} |
|
if (String.prototype.localeCompare) { |
|
$scope.countries.sort(function(a, b) { |
|
return a.name.localeCompare(b.name); |
|
}); |
|
} |
|
}); |
|
}) |
|
|
|
|
|
.controller('PhonebookModalController', function ($scope, $modalInstance, $rootScope, AppUsersManager, PhonebookContactsService, ErrorService) { |
|
|
|
$scope.search = {}; |
|
$scope.phonebook = []; |
|
$scope.selectedContacts = {}; |
|
$scope.selectedCount = 0; |
|
$scope.slice = {limit: 20, limitDelta: 20}; |
|
$scope.progress = {enabled: false}; |
|
$scope.multiSelect = true; |
|
|
|
var searchIndex = SearchIndexManager.createIndex(), |
|
phonebookReady = false; |
|
|
|
PhonebookContactsService.getPhonebookContacts().then(function (phonebook) { |
|
for (var i = 0; i < phonebook.length; i++) { |
|
SearchIndexManager.indexObject(i, phonebook[i].first_name + ' ' + phonebook[i].last_name + ' ' + phonebook[i].phones.join(' '), searchIndex); |
|
} |
|
$scope.phonebook = phonebook; |
|
$scope.toggleSelection(true); |
|
phonebookReady = true; |
|
updateList(); |
|
}, function (error) { |
|
ErrorService.show({ |
|
error: {code: 403, type: 'PHONEBOOK_GET_CONTACTS_FAILED', originalError: error} |
|
}); |
|
}); |
|
|
|
function updateList () { |
|
var filtered = false, |
|
results = {}; |
|
|
|
if (angular.isString($scope.search.query) && $scope.search.query.length) { |
|
filtered = true; |
|
results = SearchIndexManager.search($scope.search.query, searchIndex); |
|
|
|
$scope.contacts = []; |
|
delete $scope.contactsEmpty; |
|
for (var i = 0; i < $scope.phonebook.length; i++) { |
|
if (!filtered || results[i]) { |
|
$scope.contacts.push($scope.phonebook[i]); |
|
} |
|
} |
|
} else { |
|
$scope.contacts = $scope.phonebook; |
|
$scope.contactsEmpty = !$scope.contacts.length; |
|
} |
|
|
|
$scope.slice.limit = 20; |
|
} |
|
|
|
$scope.$watch('search.query', function (newValue) { |
|
if (phonebookReady) { |
|
updateList(); |
|
} |
|
}); |
|
|
|
$scope.contactSelect = function (i) { |
|
if (!$scope.multiSelect) { |
|
return $modalInstance.close($scope.phonebook[i]); |
|
} |
|
if ($scope.selectedContacts[i]) { |
|
delete $scope.selectedContacts[i]; |
|
$scope.selectedCount--; |
|
} else { |
|
$scope.selectedContacts[i] = true; |
|
$scope.selectedCount++; |
|
} |
|
}; |
|
|
|
$scope.toggleSelection = function (fill) { |
|
if (!$scope.selectedCount || fill) { |
|
$scope.selectedCount = $scope.phonebook.length; |
|
for (var i = 0; i < $scope.phonebook.length; i++) { |
|
$scope.selectedContacts[i] = true; |
|
} |
|
} else { |
|
$scope.selectedCount = 0; |
|
$scope.selectedContacts = {}; |
|
} |
|
}; |
|
|
|
$scope.submitSelected = function () { |
|
if ($scope.selectedCount <= 0) { |
|
$modalInstance.dismiss(); |
|
} |
|
|
|
var selectedContacts = []; |
|
angular.forEach($scope.selectedContacts, function (t, i) { |
|
selectedContacts.push($scope.phonebook[i]); |
|
}); |
|
|
|
ErrorService.confirm({ |
|
type: 'CONTACTS_IMPORT_PERFORM' |
|
}).then(function () { |
|
$scope.progress.enabled = true; |
|
AppUsersManager.importContacts(selectedContacts).then(function (foundContacts) { |
|
if (!foundContacts.length) { |
|
ErrorService.show({ |
|
error: {code: 404, type: 'USERS_NOT_USING_TELEGRAM'} |
|
}); |
|
} |
|
$modalInstance.close(foundContacts); |
|
})['finally'](function () { |
|
$scope.progress.enabled = false; |
|
}); |
|
}); |
|
}; |
|
|
|
})
|
|
|