diff options
-rw-r--r-- | webclient/app-controller.js | 24 | ||||
-rw-r--r-- | webclient/app.css | 12 | ||||
-rw-r--r-- | webclient/app.js | 15 | ||||
-rw-r--r-- | webclient/home/home-controller.js | 162 | ||||
-rw-r--r-- | webclient/home/home.html | 63 | ||||
-rw-r--r-- | webclient/index.html | 14 | ||||
-rw-r--r-- | webclient/login/login-controller.js | 4 | ||||
-rw-r--r-- | webclient/room/room-controller.js | 2 | ||||
-rw-r--r-- | webclient/rooms/rooms-controller.js | 300 | ||||
-rw-r--r-- | webclient/rooms/rooms.html | 102 | ||||
-rw-r--r-- | webclient/settings/settings-controller.js | 146 | ||||
-rw-r--r-- | webclient/settings/settings.html | 73 |
12 files changed, 464 insertions, 453 deletions
diff --git a/webclient/app-controller.js b/webclient/app-controller.js index 92ad01e4f9..84cb94dc74 100644 --- a/webclient/app-controller.js +++ b/webclient/app-controller.js @@ -31,31 +31,15 @@ angular.module('MatrixWebClientController', ['matrixService']) $rootScope.$on('$routeChangeSuccess', function (event, current, previous) { $scope.location = $location.path(); }); - - - // Manage the display of the current config - $scope.config; - - // Toggles the config display - $scope.showConfig = function() { - if ($scope.config) { - $scope.config = undefined; - } - else { - $scope.config = matrixService.config(); - } - }; - - $scope.closeConfig = function() { - if ($scope.config) { - $scope.config = undefined; - } - }; if (matrixService.isUserLoggedIn()) { // eventStreamService.resume(); } + $scope.go = function(url) { + $location.url(url); + }; + // Logs the user out $scope.logout = function() { // kill the event stream diff --git a/webclient/app.css b/webclient/app.css index 7fe3cb3675..dfa17fae62 100644 --- a/webclient/app.css +++ b/webclient/app.css @@ -384,18 +384,6 @@ h1 { float: right; } -#config { - position: absolute; - z-index: 100; - top: 100px; - left: 50%; - width: 500px; - margin-left: -250px; - text-align: center; - padding: 20px; - background-color: #aaa; -} - .text_entry_section { position: fixed; bottom: 0; diff --git a/webclient/app.js b/webclient/app.js index 944b8ec270..e5d8513944 100644 --- a/webclient/app.js +++ b/webclient/app.js @@ -19,7 +19,8 @@ var matrixWebClient = angular.module('matrixWebClient', [ 'MatrixWebClientController', 'LoginController', 'RoomController', - 'RoomsController', + 'HomeController', + 'SettingsController', 'UserController', 'matrixService', 'eventStreamService', @@ -44,16 +45,20 @@ matrixWebClient.config(['$routeProvider', '$provide', '$httpProvider', templateUrl: 'room/room.html', controller: 'RoomController' }). - when('/rooms', { - templateUrl: 'rooms/rooms.html', - controller: 'RoomsController' + when('/home', { + templateUrl: 'home/home.html', + controller: 'HomeController' + }). + when('/settings', { + templateUrl: 'settings/settings.html', + controller: 'SettingsController' }). when('/user/:user_matrix_id', { templateUrl: 'user/user.html', controller: 'UserController' }). otherwise({ - redirectTo: '/rooms' + redirectTo: '/home' }); $provide.factory('AccessTokenInterceptor', ['$q', '$rootScope', diff --git a/webclient/home/home-controller.js b/webclient/home/home-controller.js new file mode 100644 index 0000000000..35d0ef1654 --- /dev/null +++ b/webclient/home/home-controller.js @@ -0,0 +1,162 @@ +/* +Copyright 2014 matrix.org + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +'use strict'; + +angular.module('HomeController', ['matrixService', 'mFileInput', 'mFileUpload', 'eventHandlerService']) +.controller('HomeController', ['$scope', '$location', 'matrixService', 'mFileUpload', 'eventHandlerService', 'eventStreamService', + function($scope, $location, matrixService, mFileUpload, eventHandlerService, eventStreamService) { + + $scope.config = matrixService.config(); + $scope.rooms = {}; + $scope.public_rooms = []; + $scope.newRoomId = ""; + $scope.feedback = ""; + + $scope.newRoom = { + room_id: "", + private: false + }; + + $scope.goToRoom = { + room_id: "", + }; + + $scope.joinAlias = { + room_alias: "", + }; + + $scope.$on(eventHandlerService.MEMBER_EVENT, function(ngEvent, event, isLive) { + var config = matrixService.config(); + if (event.target_user_id === config.user_id && event.content.membership === "invite") { + console.log("Invited to room " + event.room_id); + // FIXME push membership to top level key to match /im/sync + event.membership = event.content.membership; + // FIXME bodge a nicer name than the room ID for this invite. + event.room_display_name = event.user_id + "'s room"; + $scope.rooms[event.room_id] = event; + } + }); + + var assignRoomAliases = function(data) { + for (var i=0; i<data.length; i++) { + var alias = matrixService.getRoomIdToAliasMapping(data[i].room_id); + if (alias) { + // use the existing alias from storage + data[i].room_alias = alias; + data[i].room_display_name = alias; + } + else if (data[i].aliases && data[i].aliases[0]) { + // save the mapping + // TODO: select the smarter alias from the array + matrixService.createRoomIdToAliasMapping(data[i].room_id, data[i].aliases[0]); + data[i].room_display_name = data[i].aliases[0]; + } + else if (data[i].membership == "invite" && "inviter" in data[i]) { + data[i].room_display_name = data[i].inviter + "'s room" + } + else { + // last resort use the room id + data[i].room_display_name = data[i].room_id; + } + } + return data; + }; + + $scope.refresh = function() { + // List all rooms joined or been invited to + matrixService.rooms().then( + function(response) { + var data = assignRoomAliases(response.data.rooms); + $scope.feedback = "Success"; + for (var i=0; i<data.length; i++) { + $scope.rooms[data[i].room_id] = data[i]; + } + + var presence = response.data.presence; + for (var i = 0; i < presence.length; ++i) { + eventHandlerService.handleEvent(presence[i], false); + } + }, + function(error) { + $scope.feedback = "Failure: " + error.data; + }); + + matrixService.publicRooms().then( + function(response) { + $scope.public_rooms = assignRoomAliases(response.data.chunk); + } + ); + + eventStreamService.resume(); + }; + + $scope.createNewRoom = function(room_id, isPrivate) { + + var visibility = "public"; + if (isPrivate) { + visibility = "private"; + } + + matrixService.create(room_id, visibility).then( + function(response) { + // This room has been created. Refresh the rooms list + console.log("Created room " + response.data.room_alias + " with id: "+ + response.data.room_id); + matrixService.createRoomIdToAliasMapping( + response.data.room_id, response.data.room_alias); + $scope.refresh(); + }, + function(error) { + $scope.feedback = "Failure: " + error.data; + }); + }; + + // Go to a room + $scope.goToRoom = function(room_id) { + // Simply open the room page on this room id + //$location.url("room/" + room_id); + matrixService.join(room_id).then( + function(response) { + if (response.data.hasOwnProperty("room_id")) { + if (response.data.room_id != room_id) { + $location.url("room/" + response.data.room_id); + return; + } + } + + $location.url("room/" + room_id); + }, + function(error) { + $scope.feedback = "Can't join room: " + error.data; + } + ); + }; + + $scope.joinAlias = function(room_alias) { + matrixService.joinAlias(room_alias).then( + function(response) { + // Go to this room + $location.url("room/" + room_alias); + }, + function(error) { + $scope.feedback = "Can't join room: " + error.data; + } + ); + }; + + $scope.refresh(); +}]); diff --git a/webclient/home/home.html b/webclient/home/home.html new file mode 100644 index 0000000000..4818d414b6 --- /dev/null +++ b/webclient/home/home.html @@ -0,0 +1,63 @@ +<div ng-controller="HomeController"> + + <div id="page"> + <div id="wrapper"> + + <div> + <form> + <table> + <tr> + <td> + <div class="profile-avatar"> + <img ng-src="{{ config.avatarUrl || 'img/default-profile.jpg' }}"/> + </div> + </td> + <td> + <div id="user-ids"> + <div id="user-displayname">{{ config.displayName }}</div> + <div>{{ config.user_id }}</div> + </div> + </td> + </tr> + </table> + </form> + </div> + + <h3>My rooms</h3> + + <div class="rooms" ng-repeat="(rm_id, room) in rooms"> + <div> + <a href="#/room/{{ room.room_alias ? room.room_alias : rm_id }}" >{{ room.room_display_name }}</a> {{room.membership === 'invite' ? ' (invited)' : ''}} + </div> + </div> + <br/> + + <h3>Public rooms</h3> + + <div class="public_rooms" ng-repeat="room in public_rooms"> + <div> + <a href="#/room/{{ room.room_alias ? room.room_alias : room.room_id }}" >{{ room.room_alias }}</a> + </div> + </div> + <br/> + + <div> + <form> + <input size="40" ng-model="newRoom.room_id" ng-enter="createNewRoom(newRoom.room_id, newRoom.private)" placeholder="(e.g. foo_channel)"/> + <input type="checkbox" ng-model="newRoom.private">private + <button ng-disabled="!newRoom.room_id" ng-click="createNewRoom(newRoom.room_id, newRoom.private)">Create room</button> + </form> + </div> + <div> + <form> + <input size="40" ng-model="joinAlias.room_alias" ng-enter="joinAlias(joinAlias.room_alias)" placeholder="(e.g. #foo_channel:example.org)"/> + <button ng-disabled="!joinAlias.room_alias" ng-click="joinAlias(joinAlias.room_alias)">Join room</button> + </form> + </div> + <br/> + + {{ feedback }} + + </div> + </div> +</div> diff --git a/webclient/index.html b/webclient/index.html index 5b8e27fa6d..938d70c86d 100644 --- a/webclient/index.html +++ b/webclient/index.html @@ -17,10 +17,11 @@ <script src="app-controller.js"></script> <script src="app-directive.js"></script> <script src="app-filter.js"></script> + <script src="home/home-controller.js"></script> <script src="login/login-controller.js"></script> <script src="room/room-controller.js"></script> <script src="room/room-directive.js"></script> - <script src="rooms/rooms-controller.js"></script> + <script src="settings/settings-controller.js"></script> <script src="user/user-controller.js"></script> <script src="components/matrix/matrix-service.js"></script> <script src="components/matrix/event-stream-service.js"></script> @@ -35,20 +36,11 @@ <header id="header"> <!-- Do not show buttons on the login page --> <div id="header-buttons" ng-hide="'/login' == location "> - <button ng-click="showConfig()">Config</button> + <button ng-click='go("settings")'>Settings</button> <button ng-click="logout()">Log out</button> </div> </header> - <div id="config" ng-hide="!config"> - <div>Home server: {{ config.homeserver }} </div> - <div>User ID: {{ config.user_id }} </div> - <div>Access token: {{ config.access_token }} </div> - <div><button ng-click="requestNotifications()">Request notifications</button></div> - <div><button ng-click="closeConfig()">Close</button></div> - </div> - - <div ng-view></div> </body> diff --git a/webclient/login/login-controller.js b/webclient/login/login-controller.js index e3d0eca946..51f9a3bdf4 100644 --- a/webclient/login/login-controller.js +++ b/webclient/login/login-controller.js @@ -53,7 +53,7 @@ angular.module('LoginController', ['matrixService']) matrixService.saveConfig(); eventStreamService.resume(); // Go to the user's rooms list page - $location.url("rooms"); + $location.url("home"); }, function(error) { if (error.data) { @@ -86,7 +86,7 @@ angular.module('LoginController', ['matrixService']) }); matrixService.saveConfig(); eventStreamService.resume(); - $location.url("rooms"); + $location.url("home"); } else { $scope.feedback = "Failed to login: " + JSON.stringify(response.data); diff --git a/webclient/room/room-controller.js b/webclient/room/room-controller.js index 58ba432ce5..3311618825 100644 --- a/webclient/room/room-controller.js +++ b/webclient/room/room-controller.js @@ -372,7 +372,7 @@ angular.module('RoomController', ['ngSanitize', 'mUtilities']) matrixService.leave($scope.room_id).then( function(response) { console.log("Left room "); - $location.url("rooms"); + $location.url("home"); }, function(error) { $scope.feedback = "Failed to leave room: " + error.data.error; diff --git a/webclient/rooms/rooms-controller.js b/webclient/rooms/rooms-controller.js deleted file mode 100644 index d9c8baff47..0000000000 --- a/webclient/rooms/rooms-controller.js +++ /dev/null @@ -1,300 +0,0 @@ -/* -Copyright 2014 matrix.org - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -angular.module('RoomsController', ['matrixService', 'mFileInput', 'mFileUpload', 'eventHandlerService']) -.controller('RoomsController', ['$scope', '$location', 'matrixService', 'mFileUpload', 'eventHandlerService', 'eventStreamService', - function($scope, $location, matrixService, mFileUpload, eventHandlerService, eventStreamService) { - - $scope.rooms = {}; - $scope.public_rooms = []; - $scope.newRoomId = ""; - $scope.feedback = ""; - - $scope.newRoom = { - room_id: "", - private: false - }; - - $scope.goToRoom = { - room_id: "", - }; - - $scope.joinAlias = { - room_alias: "", - }; - - $scope.newProfileInfo = { - name: matrixService.config().displayName, - avatar: matrixService.config().avatarUrl, - avatarFile: undefined - }; - - $scope.linkedEmails = { - linkNewEmail: "", // the email entry box - emailBeingAuthed: undefined, // to populate verification text - authTokenId: undefined, // the token id from the IS - clientSecret: undefined, // our client secret - sendAttempt: 1, - emailCode: "", // the code entry box - linkedEmailList: matrixService.config().emailList // linked email list - }; - - $scope.$on(eventHandlerService.MEMBER_EVENT, function(ngEvent, event, isLive) { - var config = matrixService.config(); - if (event.target_user_id === config.user_id && event.content.membership === "invite") { - console.log("Invited to room " + event.room_id); - // FIXME push membership to top level key to match /im/sync - event.membership = event.content.membership; - // FIXME bodge a nicer name than the room ID for this invite. - event.room_display_name = event.user_id + "'s room"; - $scope.rooms[event.room_id] = event; - } - }); - - var assignRoomAliases = function(data) { - for (var i=0; i<data.length; i++) { - var alias = matrixService.getRoomIdToAliasMapping(data[i].room_id); - if (alias) { - // use the existing alias from storage - data[i].room_alias = alias; - data[i].room_display_name = alias; - } - else if (data[i].aliases && data[i].aliases[0]) { - // save the mapping - // TODO: select the smarter alias from the array - matrixService.createRoomIdToAliasMapping(data[i].room_id, data[i].aliases[0]); - data[i].room_display_name = data[i].aliases[0]; - } - else if (data[i].membership == "invite" && "inviter" in data[i]) { - data[i].room_display_name = data[i].inviter + "'s room" - } - else { - // last resort use the room id - data[i].room_display_name = data[i].room_id; - } - } - return data; - }; - - $scope.refresh = function() { - // List all rooms joined or been invited to - matrixService.rooms().then( - function(response) { - var data = assignRoomAliases(response.data.rooms); - $scope.feedback = "Success"; - for (var i=0; i<data.length; i++) { - $scope.rooms[data[i].room_id] = data[i]; - } - - var presence = response.data.presence; - for (var i = 0; i < presence.length; ++i) { - eventHandlerService.handleEvent(presence[i], false); - } - }, - function(error) { - $scope.feedback = "Failure: " + error.data; - }); - - matrixService.publicRooms().then( - function(response) { - $scope.public_rooms = assignRoomAliases(response.data.chunk); - } - ); - - eventStreamService.resume(); - }; - - $scope.createNewRoom = function(room_id, isPrivate) { - - var visibility = "public"; - if (isPrivate) { - visibility = "private"; - } - - matrixService.create(room_id, visibility).then( - function(response) { - // This room has been created. Refresh the rooms list - console.log("Created room " + response.data.room_alias + " with id: "+ - response.data.room_id); - matrixService.createRoomIdToAliasMapping( - response.data.room_id, response.data.room_alias); - $scope.refresh(); - }, - function(error) { - $scope.feedback = "Failure: " + error.data; - }); - }; - - // Go to a room - $scope.goToRoom = function(room_id) { - // Simply open the room page on this room id - //$location.url("room/" + room_id); - matrixService.join(room_id).then( - function(response) { - if (response.data.hasOwnProperty("room_id")) { - if (response.data.room_id != room_id) { - $location.url("room/" + response.data.room_id); - return; - } - } - - $location.url("room/" + room_id); - }, - function(error) { - $scope.feedback = "Can't join room: " + error.data; - } - ); - }; - - $scope.joinAlias = function(room_alias) { - matrixService.joinAlias(room_alias).then( - function(response) { - // Go to this room - $location.url("room/" + room_alias); - }, - function(error) { - $scope.feedback = "Can't join room: " + error.data; - } - ); - }; - - $scope.setDisplayName = function(newName) { - matrixService.setDisplayName(newName).then( - function(response) { - $scope.feedback = "Updated display name."; - var config = matrixService.config(); - config.displayName = newName; - matrixService.setConfig(config); - matrixService.saveConfig(); - }, - function(error) { - $scope.feedback = "Can't update display name: " + error.data; - } - ); - }; - - - $scope.$watch("newProfileInfo.avatarFile", function(newValue, oldValue) { - if ($scope.newProfileInfo.avatarFile) { - console.log("Uploading new avatar file..."); - mFileUpload.uploadFile($scope.newProfileInfo.avatarFile).then( - function(url) { - $scope.newProfileInfo.avatar = url; - $scope.setAvatar($scope.newProfileInfo.avatar); - }, - function(error) { - $scope.feedback = "Can't upload image"; - } - ); - } - }); - - $scope.setAvatar = function(newUrl) { - console.log("Updating avatar to "+newUrl); - matrixService.setProfilePictureUrl(newUrl).then( - function(response) { - console.log("Updated avatar"); - $scope.feedback = "Updated avatar."; - var config = matrixService.config(); - config.avatarUrl = newUrl; - matrixService.setConfig(config); - matrixService.saveConfig(); - }, - function(error) { - $scope.feedback = "Can't update avatar: " + error.data; - } - ); - }; - - var generateClientSecret = function() { - var ret = ""; - var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - - for (var i = 0; i < 32; i++) { - ret += chars.charAt(Math.floor(Math.random() * chars.length)); - } - - return ret; - }; - - - $scope.linkEmail = function(email) { - if (email != $scope.linkedEmails.emailBeingAuthed) { - $scope.linkedEmails.clientSecret = generateClientSecret(); - $scope.linkedEmails.sendAttempt = 1; - } - matrixService.linkEmail(email, $scope.linkedEmails.clientSecret, $scope.linkedEmails.sendAttempt).then( - function(response) { - if (response.data.success === true) { - $scope.linkedEmails.authTokenId = response.data.sid; - $scope.emailFeedback = "You have been sent an email."; - $scope.linkedEmails.emailBeingAuthed = email; - } - else { - $scope.emailFeedback = "Failed to send email."; - } - }, - function(error) { - $scope.emailFeedback = "Can't send email: " + error.data; - } - ); - }; - - $scope.submitEmailCode = function(code) { - var tokenId = $scope.linkedEmails.authTokenId; - if (tokenId === undefined) { - $scope.emailFeedback = "You have not requested a code with this email."; - return; - } - matrixService.authEmail(matrixService.config().user_id, tokenId, code, $scope.linkedEmails.clientSecret).then( - function(response) { - if ("success" in response.data && response.data.success === false) { - $scope.emailFeedback = "Failed to authenticate email."; - return; - } - matrixService.bindEmail(matrixService.config().user_id, tokenId, $scope.linkedEmails.clientSecret).then( - function(response) { - var config = matrixService.config(); - var emailList = {}; - if ("emailList" in config) { - emailList = config.emailList; - } - emailList[$scope.linkedEmails.emailBeingAuthed] = response; - // save the new email list - config.emailList = emailList; - matrixService.setConfig(config); - matrixService.saveConfig(); - // invalidate the email being authed and update UI. - $scope.linkedEmails.emailBeingAuthed = undefined; - $scope.emailFeedback = ""; - $scope.linkedEmails.linkedEmailList = emailList; - $scope.linkedEmails.linkNewEmail = ""; - $scope.linkedEmails.emailCode = ""; - }, function(reason) { - $scope.emailFeedback = "Failed to link email: " + reason; - } - ); - }, - function(reason) { - $scope.emailFeedback = "Failed to auth email: " + reason; - } - ); - }; - - $scope.refresh(); -}]); diff --git a/webclient/rooms/rooms.html b/webclient/rooms/rooms.html deleted file mode 100644 index 2a12cbc8ae..0000000000 --- a/webclient/rooms/rooms.html +++ /dev/null @@ -1,102 +0,0 @@ -<div ng-controller="RoomsController" class="rooms"> - <h1 id="logo">[matrix]</h1> - - <div id="page"> - <div id="wrapper"> - - <div> - <form> - <table> - <tr> - <td> - <div class="profile-avatar"> - <img ng-src="{{ newProfileInfo.avatar || 'img/default-profile.jpg' }}" m-file-input="newProfileInfo.avatarFile"/> - </div> - </td> - <td> - <!-- TODO: To enable once we have an upload server - <button m-file-input="newProfileInfo.avatarFile">Upload new Avatar</button> - or use an existing image URL: - --> - <div> - <input size="40" ng-model="newProfileInfo.avatar" ng-enter="setAvatar(newProfileInfo.avatar)" placeholder="Image URL"/> - <button ng-disabled="!newProfileInfo.avatar" ng-click="setAvatar(newProfileInfo.avatar)">Update Avatar URL</button> - </div> - </td> - </tr> - </table> - </form> - </div> - - <div> - <form> - <input size="40" ng-model="newProfileInfo.name" ng-enter="setDisplayName(newProfileInfo.name)" /> - <button ng-disabled="!newProfileInfo.name" ng-click="setDisplayName(newProfileInfo.name)">Update Name</button> - </form> - </div> - - <br/> - - <div> - <form> - <input size="40" ng-model="linkedEmails.linkNewEmail" ng-enter="linkEmail(linkedEmails.linkNewEmail)" /> - <button ng-disabled="!linkedEmails.linkNewEmail" ng-click="linkEmail(linkedEmails.linkNewEmail)"> - Link Email - </button> - {{ emailFeedback }} - </form> - <form ng-hide="!linkedEmails.emailBeingAuthed"> - Enter validation token for {{ linkedEmails.emailBeingAuthed }}: - <br /> - <input size="20" ng-model="linkedEmails.emailCode" ng-enter="submitEmailCode(linkedEmails.emailCode)" /> - <button ng-disabled="!linkedEmails.emailCode || !linkedEmails.linkNewEmail" ng-click="submitEmailCode(linkedEmails.emailCode)"> - Submit Code - </button> - </form> - Linked emails: - <table> - <tr ng-repeat="(address, info) in linkedEmails.linkedEmailList"> - <td>{{address}}</td> - </tr> - </table> - </div> - <br/> - - <h3>My rooms</h3> - - <div class="rooms" ng-repeat="(rm_id, room) in rooms"> - <div> - <a href="#/room/{{ room.room_alias ? room.room_alias : rm_id }}" >{{ room.room_display_name }}</a> {{room.membership === 'invite' ? ' (invited)' : ''}} - </div> - </div> - <br/> - - <h3>Public rooms</h3> - - <div class="public_rooms" ng-repeat="room in public_rooms"> - <div> - <a href="#/room/{{ room.room_alias ? room.room_alias : room.room_id }}" >{{ room.room_alias }}</a> - </div> - </div> - <br/> - - <div> - <form> - <input size="40" ng-model="newRoom.room_id" ng-enter="createNewRoom(newRoom.room_id, newRoom.private)" placeholder="(e.g. foo_channel)"/> - <input type="checkbox" ng-model="newRoom.private">private - <button ng-disabled="!newRoom.room_id" ng-click="createNewRoom(newRoom.room_id, newRoom.private)">Create room</button> - </form> - </div> - <div> - <form> - <input size="40" ng-model="joinAlias.room_alias" ng-enter="joinAlias(joinAlias.room_alias)" placeholder="(e.g. #foo_channel:example.org)"/> - <button ng-disabled="!joinAlias.room_alias" ng-click="joinAlias(joinAlias.room_alias)">Join room</button> - </form> - </div> - <br/> - - {{ feedback }} - - </div> - </div> -</div> diff --git a/webclient/settings/settings-controller.js b/webclient/settings/settings-controller.js new file mode 100644 index 0000000000..5d3f7cb2b8 --- /dev/null +++ b/webclient/settings/settings-controller.js @@ -0,0 +1,146 @@ +/* +Copyright 2014 matrix.org + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +'use strict'; + +angular.module('SettingsController', ['matrixService', 'mFileUpload']) +.controller('SettingsController', ['$scope', 'matrixService', 'mFileUpload', + function($scope, matrixService, mFileUpload) { + $scope.config = matrixService.config(); + + $scope.profile = { + displayName: $scope.config.displayName, + avatarUrl: $scope.config.avatarUrl + }; + + $scope.$watch("profile.avatarFile", function(newValue, oldValue) { + if ($scope.profile.avatarFile) { + console.log("Uploading new avatar file..."); + mFileUpload.uploadFile($scope.profile.avatarFile).then( + function(url) { + $scope.profile.avatarUrl = url; + }, + function(error) { + $scope.feedback = "Can't upload image"; + } + ); + } + }); + + $scope.saveProfile = function() { + if ($scope.profile.displayName !== $scope.config.displayName) { + setDisplayName($scope.profile.displayName); + } + if ($scope.profile.avatarUrl !== $scope.config.avatarUrl) { + setAvatar($scope.profile.avatarUrl); + } + }; + + var setDisplayName = function(displayName) { + matrixService.setDisplayName(displayName).then( + function(response) { + $scope.feedback = "Updated display name."; + + var config = matrixService.config(); + config.displayName = displayName; + matrixService.setConfig(config); + matrixService.saveConfig(); + }, + function(error) { + $scope.feedback = "Can't update display name: " + error.data; + } + ); + }; + + var setAvatar = function(avatarURL) { + console.log("Updating avatar to " + avatarURL); + matrixService.setProfilePictureUrl(avatarURL).then( + function(response) { + console.log("Updated avatar"); + $scope.feedback = "Updated avatar."; + + var config = matrixService.config(); + config.avatarUrl = avatarURL; + matrixService.setConfig(config); + matrixService.saveConfig(); + }, + function(error) { + $scope.feedback = "Can't update avatar: " + error.data; + } + ); + }; + + $scope.linkedEmails = { + linkNewEmail: "", // the email entry box + emailBeingAuthed: undefined, // to populate verification text + authTokenId: undefined, // the token id from the IS + emailCode: "", // the code entry box + linkedEmailList: matrixService.config().emailList // linked email list + }; + + $scope.linkEmail = function(email) { + matrixService.linkEmail(email).then( + function(response) { + if (response.data.success === true) { + $scope.linkedEmails.authTokenId = response.data.tokenId; + $scope.emailFeedback = "You have been sent an email."; + $scope.linkedEmails.emailBeingAuthed = email; + } + else { + $scope.emailFeedback = "Failed to send email."; + } + }, + function(error) { + $scope.emailFeedback = "Can't send email: " + error.data; + } + ); + }; + + $scope.submitEmailCode = function(code) { + var tokenId = $scope.linkedEmails.authTokenId; + if (tokenId === undefined) { + $scope.emailFeedback = "You have not requested a code with this email."; + return; + } + matrixService.authEmail(matrixService.config().user_id, tokenId, code).then( + function(response) { + if ("success" in response.data && response.data.success === false) { + $scope.emailFeedback = "Failed to authenticate email."; + return; + } + var config = matrixService.config(); + var emailList = {}; + if ("emailList" in config) { + emailList = config.emailList; + } + emailList[response.address] = response; + // save the new email list + config.emailList = emailList; + matrixService.setConfig(config); + matrixService.saveConfig(); + // invalidate the email being authed and update UI. + $scope.linkedEmails.emailBeingAuthed = undefined; + $scope.emailFeedback = ""; + $scope.linkedEmails.linkedEmailList = emailList; + $scope.linkedEmails.linkNewEmail = ""; + $scope.linkedEmails.emailCode = ""; + }, + function(reason) { + $scope.emailFeedback = "Failed to auth email: " + reason; + } + ); + }; +}]); \ No newline at end of file diff --git a/webclient/settings/settings.html b/webclient/settings/settings.html new file mode 100644 index 0000000000..453a4fc35f --- /dev/null +++ b/webclient/settings/settings.html @@ -0,0 +1,73 @@ +<div ng-controller="SettingsController" class="user"> + + <div id="page"> + <div id="wrapper"> + + <h3>Me</h3> + <div> + <form> + <table> + <tr> + <td> + <div class="profile-avatar"> + <img ng-src="{{ profile.avatarUrl || 'img/default-profile.jpg' }}" m-file-input="profile.avatarFile"/> + </div> + </td> + <td> + <div id="user-ids"> + <input size="40" ng-model="profile.displayName" placeholder="Your name"/> + </div> + </td> + <td> + <button ng-disabled="(profile.displayName == config.displayName) && (profile.avatarUrl == config.avatarUrl)" + ng-click="saveProfile()">Save</button> + </td> + </tr> + </table> + </form> + </div> + <br/> + + <h3>Linked emails</h3> + <div> + <form> + <input size="40" ng-model="linkedEmails.linkNewEmail" ng-enter="linkEmail(linkedEmails.linkNewEmail)" /> + <button ng-disabled="!linkedEmails.linkNewEmail" ng-click="linkEmail(linkedEmails.linkNewEmail)"> + Link Email + </button> + {{ emailFeedback }} + </form> + <form ng-hide="!linkedEmails.emailBeingAuthed"> + Enter validation token for {{ linkedEmails.emailBeingAuthed }}: + <br /> + <input size="20" ng-model="linkedEmails.emailCode" ng-enter="submitEmailCode(linkedEmails.emailCode)" /> + <button ng-disabled="!linkedEmails.emailCode || !linkedEmails.linkNewEmail" ng-click="submitEmailCode(linkedEmails.emailCode)"> + Submit Code + </button> + </form> + <table> + <tr ng-repeat="(address, info) in linkedEmails.linkedEmailList"> + <td>{{address}}</td> + </tr> + </table> + </div> + <br/> + + <h3>Configuration</h3> + <div> + <div>Home server: {{ config.homeserver }} </div> + <div>User ID: {{ config.user_id }} </div> + <div>Access token: {{ config.access_token }} </div> + </div> + <br/> + + <div> + <div><button ng-click="requestNotifications()">Request notifications</button></div> + </div> + <br/> + + {{ feedback }} + + </div> + </div> +</div> |