Browse Source

Added usernames search, improved username settings

master
Igor Zhukov 10 years ago
parent
commit
671022fb9b
  1. 10
      app/css/app.css
  2. 4
      app/css/desktop.css
  3. 2
      app/css/mobile.css
  4. 110
      app/js/controllers.js
  5. 3
      app/js/locales/en-us.json
  6. 6
      app/js/services.js
  7. 13
      app/partials/desktop/changelog_modal.html
  8. 30
      app/partials/desktop/im.html
  9. 10
      app/partials/desktop/username_edit_modal.html
  10. 33
      app/partials/mobile/im.html
  11. 13
      app/partials/mobile/settings_modal.html
  12. 44
      app/partials/mobile/username_edit_modal.html

10
app/css/app.css

@ -461,6 +461,12 @@ input[type="number"] {
.modal_simple_form .form-group { .modal_simple_form .form-group {
margin-bottom: 13px; margin-bottom: 13px;
} }
.modal_simple_form_description {
color: #777;
line-height: 160%;
margin: 10px 0 0;
text-align: justify;
}
.modal_section_header { .modal_section_header {
font-size: 12px; font-size: 12px;
@ -2112,6 +2118,10 @@ img.img_fullsize {
.settings_modal_wrap .im_attach_input { .settings_modal_wrap .im_attach_input {
z-index: 999; z-index: 999;
} }
.settings_modal_username_link,
.settings_modal_username_link:hover {
color: inherit;
}
.settings_external_service { .settings_external_service {
line-height: 0; line-height: 0;
display: inline-block; display: inline-block;

4
app/css/desktop.css

@ -555,10 +555,6 @@ div.im_panel_own_photo {
.modal_section_body dd { .modal_section_body dd {
display: inline-block; display: inline-block;
} }
.settings_modal_username_link,
.settings_modal_username_link:hover {
color: inherit;
}
.user_modal_main_btn { .user_modal_main_btn {
border: 0; border: 0;

2
app/css/mobile.css

@ -181,6 +181,7 @@ html {
} }
.navbar-quick-media-back h4 { .navbar-quick-media-back h4 {
margin: 9px 0 12px 0; margin: 9px 0 12px 0;
line-height: 120%;
} }
.navbar-quick-profile-back h4, .navbar-quick-profile-back h4,
.navbar-quick-group-back h4 { .navbar-quick-group-back h4 {
@ -884,6 +885,7 @@ a.mobile_modal_action .tg_checkbox_label {
} }
.mobile_modal_section { .mobile_modal_section {
display: block;
border-bottom: 1px solid #e0e0e0; border-bottom: 1px solid #e0e0e0;
padding: 15px 0; padding: 15px 0;
} }

110
app/js/controllers.js

@ -439,6 +439,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.dialogs = []; $scope.dialogs = [];
$scope.contacts = []; $scope.contacts = [];
$scope.foundUsers = [];
$scope.contactsLoaded = false; $scope.contactsLoaded = false;
if ($scope.search === undefined) { if ($scope.search === undefined) {
$scope.search = {}; $scope.search = {};
@ -636,6 +637,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
getDialogs(force).then(function (dialogsResult) { getDialogs(force).then(function (dialogsResult) {
$scope.dialogs = []; $scope.dialogs = [];
$scope.contacts = []; $scope.contacts = [];
$scope.foundUsers = [];
if (dialogsResult.dialogs.length) { if (dialogsResult.dialogs.length) {
offset += dialogsResult.dialogs.length; offset += dialogsResult.dialogs.length;
@ -678,7 +680,6 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.contacts.push({ $scope.contacts.push({
userID: userID, userID: userID,
user: AppUsersManager.getUser(userID), user: AppUsersManager.getUser(userID),
userPhoto: AppUsersManager.getUserPhoto(userID, 'User'),
peerString: AppUsersManager.getUserString(userID) peerString: AppUsersManager.getUserString(userID)
}); });
} }
@ -689,8 +690,31 @@ angular.module('myApp.controllers', ['myApp.i18n'])
} else if (!$scope.search.query) { } else if (!$scope.search.query) {
$scope.isEmpty.contacts = true; $scope.isEmpty.contacts = true;
} }
$scope.$broadcast('ui_dialogs_append');
}); });
$scope.$broadcast('ui_dialogs_append');
if ($scope.search.query && $scope.search.query.length >= 5) {
MtpApiManager.invokeApi('contacts.search', {q: $scope.search.query, limit: 10}).then(function (result) {
console.log($scope.search.query, result);
AppUsersManager.saveApiUsers(result.users);
if (curJump != jump) 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;
}
});
}
} }
function showMoreDialogs () { function showMoreDialogs () {
@ -2214,7 +2238,17 @@ angular.module('myApp.controllers', ['myApp.i18n'])
} }
}) })
.controller('ProfileEditModalController', function ($rootScope, $scope, $timeout, $modal, $modalInstance, AppUsersManager, AppChatsManager, MtpApiManager, Storage, NotificationsManager, MtpApiFileManager, ApiUpdatesManager) { .controller('ChangelogModalController', function ($scope, $modal) {
$scope.changeUsername = function () {
$modal.open({
templateUrl: templateUrl('username_edit_modal'),
controller: 'UsernameEditModalController',
windowClass: 'username_edit_modal_window mobile_modal'
});
};
})
.controller('ProfileEditModalController', function ($scope, $modalInstance, AppUsersManager, MtpApiManager) {
$scope.profile = {}; $scope.profile = {};
$scope.error = {}; $scope.error = {};
@ -2256,6 +2290,76 @@ angular.module('myApp.controllers', ['myApp.i18n'])
} }
}) })
.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) {
switch (error.type) {
case 'USERNAME_INVALID':
$scope.checked = {error: true};
error.handled = true;
break;
case 'USERNAME_OCCUPIED':
$scope.checked = {error: true};
error.handled = true;
break;
case 'USERNAME_NOT_MODIFIED':
error.handled = true;
$modalInstance.close();
break;
}
})['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, $modal, $modalInstance, AppUsersManager, ErrorService) { .controller('ContactsModalController', function ($scope, $modal, $modalInstance, AppUsersManager, ErrorService) {
$scope.contacts = []; $scope.contacts = [];

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

@ -59,7 +59,7 @@
"username_edit_modal_title": "Change username", "username_edit_modal_title": "Change username",
"username_edit_placeholder": "Username", "username_edit_placeholder": "Username",
"username_edit_description_md": "Username lets other people find you and have a chat in\n**Telegram** without exposing your phone number.\n\nYou can only use symbols like a-z and 0-9.", "username_edit_description_md": "Choose a username so that other people can find you on **Telegram** and message you without knowing your phone number.\n\nYou can use a-z, 0-9 and underscores.",
"username_edit_submit": "Save", "username_edit_submit": "Save",
"username_edit_submit_active": "Saving...", "username_edit_submit_active": "Saving...",
@ -228,6 +228,7 @@
"head_new_contact": "New Contact", "head_new_contact": "New Contact",
"head_contacts": "Contacts", "head_contacts": "Contacts",
"head_contacts_title": "Contacts", "head_contacts_title": "Contacts",
"im_found_title": "Global search",
"head_settings": "Settings", "head_settings": "Settings",
"head_log_out": "Log Out", "head_log_out": "Log Out",
"head_edit_messages": "Edit messages", "head_edit_messages": "Edit messages",

6
app/js/services.js

@ -52,7 +52,7 @@ angular.module('myApp.services', ['myApp.i18n'])
return false; return false;
} }
return (user.first_name || '') + ' ' + (user.last_name || '') + ' ' + (user.phone || ''); return (user.first_name || '') + ' ' + (user.last_name || '') + ' ' + (user.phone || '') + ' ' + (user.username || '');
} }
function getContacts (query) { function getContacts (query) {
@ -1268,6 +1268,9 @@ angular.module('myApp.services', ['myApp.i18n'])
} }
function sendText(peerID, text) { function sendText(peerID, text) {
if (!angular.isString(text) || !text.length) {
return;
}
var messageID = tempID--, var messageID = tempID--,
randomID = [nextRandomInt(0xFFFFFFFF), nextRandomInt(0xFFFFFFFF)], randomID = [nextRandomInt(0xFFFFFFFF), nextRandomInt(0xFFFFFFFF)],
randomIDS = bigint(randomID[0]).shiftLeft(32).add(bigint(randomID[1])).toString(), randomIDS = bigint(randomID[0]).shiftLeft(32).add(bigint(randomID[1])).toString(),
@ -3947,6 +3950,7 @@ angular.module('myApp.services', ['myApp.i18n'])
}; };
$modal.open({ $modal.open({
controller: 'ChangelogModalController',
templateUrl: templateUrl('changelog_modal'), templateUrl: templateUrl('changelog_modal'),
scope: $scope, scope: $scope,
windowClass: 'changelog_modal_window mobile_modal' windowClass: 'changelog_modal_window mobile_modal'

13
app/partials/desktop/changelog_modal.html

@ -19,7 +19,20 @@
<div class="modal_section changelog_version_wrap"> <div class="modal_section changelog_version_wrap">
<h3 class="modal_section_header changelog_version_title"> <h3 class="modal_section_header changelog_version_title">
Version 0.3.2
<span class="pull-right" my-i18n="changelog_modal_title_current_version"></span> <span class="pull-right" my-i18n="changelog_modal_title_current_version"></span>
</h3>
<div class="modal_section_body changelog_version_changes">
<ul class="list-unstyled changelog_version_changes_list">
<li>Supported usernames. <a href="" ng-click="changeUsername">Set up right now!</a></li>
<li>Conversations search field is now searching public users by username.</li>
<li>Added default recent emoticons.</li>
</ul>
</div>
</div>
<div class="modal_section changelog_version_wrap">
<h3 class="modal_section_header changelog_version_title">
Version 0.3.1 Version 0.3.1
</h3> </h3>
<div class="modal_section_body changelog_version_changes"> <div class="modal_section_body changelog_version_changes">

30
app/partials/desktop/im.html

@ -57,16 +57,10 @@
<ul class="nav nav-pills nav-stacked"> <ul class="nav nav-pills nav-stacked">
<li class="im_dialog_wrap" ng-repeat="contact in contacts | orderBy:'user.sortName' track by contact.userID" ng-class="{active: curDialog.peerID == contact.userID}"> <li class="im_dialog_wrap" ng-repeat="contact in contacts | orderBy:'user.sortName' track by contact.userID" ng-class="{active: curDialog.peerID == contact.userID}">
<a class="im_dialog" ng-mousedown="dialogSelect(contact.peerString)"> <a class="im_dialog" ng-mousedown="dialogSelect(contact.peerString)">
<div class="im_dialog_photo pull-left"> <div class="im_dialog_photo pull-left" my-user-photolink="contact.userID" img-class="im_dialog_photo"></div>
<img
class="im_dialog_photo"
my-load-thumb
thumb="contact.userPhoto"
/>
</div>
<div class="im_dialog_message_wrap"> <div class="im_dialog_message_wrap">
<div class="im_dialog_peer"> <div class="im_dialog_peer">
<span class="im_dialog_user" ng-bind-html="contact.user.rFullName"></span> <span class="im_dialog_user" my-user-link="contact.userID"></span>
</div> </div>
<div class="im_dialog_message"> <div class="im_dialog_message">
<span class="im_dialog_message_text" my-user-status="::contact.userID"></span> <span class="im_dialog_message_text" my-user-status="::contact.userID"></span>
@ -77,6 +71,26 @@
</ul> </ul>
</div> </div>
<div class="im_dialogs_contacts_wrap" ng-show="!search.messages &amp;&amp; foundUsers.length > 0">
<h5 my-i18n="im_found_title"></h5>
<ul class="nav nav-pills nav-stacked">
<li class="im_dialog_wrap" ng-repeat="foundUser in foundUsers | orderBy:'user.sortName' track by foundUser.userID" ng-class="{active: curDialog.peerID == foundUser.userID}">
<a class="im_dialog" ng-mousedown="dialogSelect(foundUser.peerString)">
<div class="im_dialog_photo pull-left" my-user-photolink="foundUser.userID" img-class="im_dialog_photo"></div>
<div class="im_dialog_message_wrap">
<div class="im_dialog_peer">
<span class="im_dialog_user" my-user-link="foundUser.userID"></span>
</div>
<div class="im_dialog_message" ng-switch="foundUser.user.username.length > 0">
<span ng-switch-when="true" class="im_dialog_message_text" ng-bind="::'@' + foundUser.user.username"></span>
<span ng-switch-default class="im_dialog_message_text" my-user-status="::foundUser.userID"></span>
</div>
</div>
</a>
</li>
</ul>
</div>
</div> </div>
</div> </div>
</div> </div>

10
app/partials/desktop/username_edit_modal.html

@ -8,13 +8,9 @@
<h4 my-i18n="username_edit_modal_title"></h4> <h4 my-i18n="username_edit_modal_title"></h4>
<div class="form-group import_modal_field_wrap" ng-class="{'has-error': error.field == 'username', 'has-feedback': error.field == 'username', 'has-success': error.field == 'username'}"> <div class="form-group import_modal_field_wrap" ng-class="{'has-error': checked.error, 'has-feedback': checked.feedback.length > 0, 'has-success': checked.success}">
<label class="control-label" ng-bind="error.feedback"></label> <input class="form-control input-md" my-focused type="text" placeholder="{{'username_edit_placeholder' | i18n}}" ng-model="profile.username" name="username" ng-model-options="{debounce: 600}"/>
<input class="form-control input-sm" my-focused type="text" placeholder="{{'username_edit_placeholder' | i18n}}" ng-model="profile.username" name="username"/> <span ng-if="checked.error" class="glyphicon form-control-feedback" ng-class="{'glyphicon-remove': checked.error}"></span>
<span class="glyphicon glyphicon-remove form-control-feedback"></span>
</div>
<div class="form-group import_modal_field_wrap" ng-class="{'has-error': error.field == 'username'}">
</div> </div>
<div class="modal_simple_form_description" my-i18n="username_edit_description_md"></div> <div class="modal_simple_form_description" my-i18n="username_edit_description_md"></div>

33
app/partials/mobile/im.html

@ -41,17 +41,11 @@
<h5 my-i18n="im_contacts_title"></h5> <h5 my-i18n="im_contacts_title"></h5>
<ul class="nav nav-pills nav-stacked"> <ul class="nav nav-pills nav-stacked">
<li class="im_dialog_wrap" ng-repeat="contact in contacts | orderBy:'user.sortName' track by contact.userID" ng-class="{active: curDialog.peerID == contact.userID}"> <li class="im_dialog_wrap" ng-repeat="contact in contacts | orderBy:'user.sortName' track by contact.userID" ng-class="{active: curDialog.peerID == contact.userID}">
<a class="im_dialog" ng-click="dialogSelect(contact.peerString)"> <a class="im_dialog" ng-mousedown="dialogSelect(contact.peerString)">
<div class="im_dialog_photo pull-left"> <div class="im_dialog_photo pull-left" my-user-photolink="contact.userID" img-class="im_dialog_photo"></div>
<img
class="im_dialog_photo"
my-load-thumb
thumb="contact.userPhoto"
/>
</div>
<div class="im_dialog_message_wrap"> <div class="im_dialog_message_wrap">
<div class="im_dialog_peer"> <div class="im_dialog_peer">
<span class="im_dialog_user" ng-bind-html="contact.user.rFullName"></span> <span class="im_dialog_user" my-user-link="contact.userID"></span>
</div> </div>
<div class="im_dialog_message"> <div class="im_dialog_message">
<span class="im_dialog_message_text" my-user-status="::contact.userID"></span> <span class="im_dialog_message_text" my-user-status="::contact.userID"></span>
@ -61,6 +55,27 @@
</li> </li>
</ul> </ul>
</div> </div>
<div class="im_dialogs_contacts_wrap" ng-show="!search.messages &amp;&amp; foundUsers.length > 0">
<h5 my-i18n="im_found_title"></h5>
<ul class="nav nav-pills nav-stacked">
<li class="im_dialog_wrap" ng-repeat="foundUser in foundUsers | orderBy:'user.sortName' track by foundUser.userID" ng-class="{active: curDialog.peerID == foundUser.userID}">
<a class="im_dialog" ng-mousedown="dialogSelect(foundUser.peerString)">
<div class="im_dialog_photo pull-left" my-user-photolink="foundUser.userID" img-class="im_dialog_photo"></div>
<div class="im_dialog_message_wrap">
<div class="im_dialog_peer">
<span class="im_dialog_user" my-user-link="foundUser.userID"></span>
</div>
<div class="im_dialog_message" ng-switch="foundUser.user.username.length > 0">
<span ng-switch-when="true" class="im_dialog_message_text" ng-bind="::'@' + foundUser.user.username"></span>
<span ng-switch-default class="im_dialog_message_text" my-user-status="::foundUser.userID"></span>
</div>
</div>
</a>
</li>
</ul>
</div>
</div> </div>
</div> </div>

13
app/partials/mobile/settings_modal.html

@ -17,6 +17,9 @@
<li> <li>
<a ng-click="editProfile()" my-i18n="settings_modal_edit_profile"></a> <a ng-click="editProfile()" my-i18n="settings_modal_edit_profile"></a>
</li> </li>
<li>
<a ng-click="changeUsername()" my-i18n="settings_modal_edit_username"></a>
</li>
<li> <li>
<a ng-click="terminateSessions()" my-i18n="settings_modal_terminate_sessions"></a> <a ng-click="terminateSessions()" my-i18n="settings_modal_terminate_sessions"></a>
</li> </li>
@ -112,10 +115,18 @@
</div> </div>
<div class="mobile_modal_section" ng-if="profile.phone"> <div class="mobile_modal_section" ng-if="profile.phone">
<h4 class="mobile_modal_section_header" my-i18n="settings_modal_phone"></h4> <h4 class="mobile_modal_section_header" my-i18n="user_modal_phone"></h4>
<div class="mobile_modal_section_value" ng-bind="profile.phone | phoneNumber"></div> <div class="mobile_modal_section_value" ng-bind="profile.phone | phoneNumber"></div>
</div> </div>
<div class="mobile_modal_section">
<h4 class="mobile_modal_section_header" my-i18n="user_modal_username"></h4>
<div class="mobile_modal_section_value" ng-click="changeUsername()" ng-switch="profile.username.length > 0">
<a class="settings_modal_username_link" ng-switch-when="true" href="" ng-click="changeUsername()" ng-bind="'@' + profile.username"></a>
<a ng-switch-default href="" ng-click="changeUsername()" my-i18n="settings_modal_empty_username_set"></a>
</div>
</div>
<div class="mobile_modal_section"> <div class="mobile_modal_section">
<h4 class="mobile_modal_section_header" my-i18n="settings_modal_about"></h4> <h4 class="mobile_modal_section_header" my-i18n="settings_modal_about"></h4>
<div class="mobile_modal_section_body settings_about_section_body clearfix"> <div class="mobile_modal_section_body settings_about_section_body clearfix">

44
app/partials/mobile/username_edit_modal.html

@ -0,0 +1,44 @@
<div class="username_edit_modal_wrap">
<div class="tg_page_head tg_modal_head">
<div class="navbar navbar-static-top navbar-inverse">
<div class="container">
<div class="navbar-header">
<ul class="nav navbar-nav navbar-quick-nav">
<li class="navbar-quick-right">
<a ng-class="{disabled: profile.updating}" ng-click="updateUsername()" ng-bind="profile.updating ? 'username_edit_submit_active' : 'username_edit_submit' | i18n" ng-disabled="profile.updating"></a>
</li>
<li>
<a ng-click="$dismiss()" class="navbar-quick-media-back">
<i class="icon icon-back"></i>
<div class="navbar-quick-back-title">
<h4 my-i18n="username_edit_modal_title"></h4>
</div>
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="modal-body">
<form class="modal_simple_form" ng-submit="updateUsername()" my-vertical-position="0.3">
<div class="form-group import_modal_field_wrap" ng-class="{'has-error': checked.error, 'has-feedback': checked.feedback.length > 0, 'has-success': checked.success}">
<input class="form-control input-md" my-focused type="text" placeholder="{{'username_edit_placeholder' | i18n}}" ng-model="profile.username" name="username" ng-model-options="{debounce: 600}"/>
<span ng-if="checked.error" class="glyphicon form-control-feedback" ng-class="{'glyphicon-remove': checked.error}"></span>
</div>
<div class="modal_simple_form_description" my-i18n="username_edit_description_md"></div>
</form>
</div>
</div>
Loading…
Cancel
Save